├── .gitignore ├── LICENSE ├── ObjectiveC_Extension.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── xcshareddata │ └── xcschemes │ └── ObjectiveC_Extension.xcscheme ├── ObjectiveC_Extension ├── CREDITS ├── Info.plist ├── NKFTPManager.h ├── NKFTPManager.m ├── NSApplication+Extension.h ├── NSApplication+Extension.m ├── NSArray+Extension.h ├── NSArray+Extension.m ├── NSAttributedString+Extension.h ├── NSAttributedString+Extension.m ├── NSBundle+Extension.h ├── NSBundle+Extension.m ├── NSColor+Extension.h ├── NSColor+Extension.m ├── NSData+Extension.h ├── NSData+Extension.m ├── NSDateFormatter+Extension.h ├── NSDateFormatter+Extension.m ├── NSException+Extension.h ├── NSException+Extension.m ├── NSFileManager+Extension.h ├── NSFileManager+Extension.m ├── NSImage+Extension.h ├── NSImage+Extension.m ├── NSMenuItem+Extension.h ├── NSMenuItem+Extension.m ├── NSMutableArray+Extension.h ├── NSMutableArray+Extension.m ├── NSMutableAttributedString+Extension.h ├── NSMutableAttributedString+Extension.m ├── NSMutableDictionary+Extension.h ├── NSMutableDictionary+Extension.m ├── NSMutableString+Extension.h ├── NSMutableString+Extension.m ├── NSMutableURLRequest+Extension.h ├── NSMutableURLRequest+Extension.m ├── NSRunningApplication+Extension.h ├── NSRunningApplication+Extension.m ├── NSSavePanel+Extension.h ├── NSSavePanel+Extension.m ├── NSScreen+Extension.h ├── NSScreen+Extension.m ├── NSString+Extension.h ├── NSString+Extension.m ├── NSTask+Extension.h ├── NSTask+Extension.m ├── NSText+Extension.h ├── NSText+Extension.m ├── NSThread+Extension.h ├── NSThread+Extension.m ├── NSTimer+Extension.h ├── NSTimer+Extension.m ├── NSUnarchiver+Extension.h ├── NSUnarchiver+Extension.m ├── NSUserDefaults+Extension.h ├── NSUserDefaults+Extension.m ├── NSView+Extension.h ├── NSView+Extension.m ├── NSWorkspace+Extension.h ├── NSWorkspace+Extension.m ├── ObjCExtensionConfig.h ├── ObjectiveC_Extension.h ├── SZJsonParser.h ├── SZJsonParser.m ├── VMMAlert.h ├── VMMAlert.m ├── VMMComputerInformation.h ├── VMMComputerInformation.m ├── VMMDeviceObserver.h ├── VMMDeviceObserver.m ├── VMMDeviceSimulator.h ├── VMMDeviceSimulator.m ├── VMMDockProgressIndicator.h ├── VMMDockProgressIndicator.m ├── VMMKeyCaptureField.h ├── VMMKeyCaptureField.m ├── VMMLocalizationUtility.h ├── VMMLogUtility.h ├── VMMLogUtility.m ├── VMMMenu.h ├── VMMMenu.m ├── VMMModals.h ├── VMMModals.m ├── VMMParentalControls.h ├── VMMParentalControls.m ├── VMMPropertyList.h ├── VMMPropertyList.m ├── VMMTextFileView.h ├── VMMTextFileView.m ├── VMMUUID.h ├── VMMUUID.m ├── VMMUsageKeycode.h ├── VMMUsageKeycode.m ├── VMMUserNotificationCenter.h ├── VMMUserNotificationCenter.m ├── VMMVersion.h ├── VMMVersion.m ├── VMMVideoCard.h ├── VMMVideoCard.m ├── VMMVideoCardManager.h ├── VMMVideoCardManager.m ├── VMMView.h ├── VMMView.m ├── VMMVirtualKeycode.h ├── VMMVirtualKeycode.m ├── VMMWebView.h ├── VMMWebView.m ├── de.lproj │ └── Localizable.strings ├── en.lproj │ └── Localizable.strings ├── fr.lproj │ └── Localizable.strings ├── nl.lproj │ └── Localizable.strings └── pt-BR.lproj │ └── Localizable.strings ├── ObjectiveC_ExtensionTests ├── Info.plist ├── NSArrayTests.m ├── NSColorTests.m ├── NSStringTests.m └── ObjectiveC_ExtensionTests.m └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | .DS_Store 6 | 7 | ## Build generated 8 | build/ 9 | DerivedData/ 10 | 11 | ## Various settings 12 | *.pbxuser 13 | !default.pbxuser 14 | *.mode1v3 15 | !default.mode1v3 16 | *.mode2v3 17 | !default.mode2v3 18 | *.perspectivev3 19 | !default.perspectivev3 20 | xcuserdata/ 21 | 22 | ## Other 23 | *.moved-aside 24 | *.xccheckout 25 | *.xcscmblueprint 26 | 27 | ## Obj-C/Swift specific 28 | *.hmap 29 | *.ipa 30 | *.dSYM.zip 31 | *.dSYM 32 | 33 | # CocoaPods 34 | # 35 | # We recommend against adding the Pods directory to your .gitignore. However 36 | # you should judge for yourself, the pros and cons are mentioned at: 37 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 38 | # 39 | # Pods/ 40 | 41 | # Carthage 42 | # 43 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 44 | # Carthage/Checkouts 45 | 46 | Carthage/Build 47 | 48 | # fastlane 49 | # 50 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 51 | # screenshots whenever they are needed. 52 | # For more information about the recommended setup visit: 53 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 54 | 55 | fastlane/report.xml 56 | fastlane/Preview.html 57 | fastlane/screenshots 58 | fastlane/test_output 59 | 60 | # Code Injection 61 | # 62 | # After new code Injection tools there's a generated folder /iOSInjectionProject 63 | # https://github.com/johnno1962/injectionforxcode 64 | 65 | iOSInjectionProject/ 66 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 vitor251093 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /ObjectiveC_Extension.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ObjectiveC_Extension.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ObjectiveC_Extension.xcodeproj/xcshareddata/xcschemes/ObjectiveC_Extension.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 64 | 65 | 71 | 72 | 73 | 74 | 75 | 76 | 82 | 83 | 89 | 90 | 91 | 92 | 94 | 95 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/CREDITS: -------------------------------------------------------------------------------- 1 | DEVELOPMENT 2 | 3 | Vitor Marques de Miranda (vitor251093) 4 | 5 | 6 | NKFTPMANAGER DEVELOPMENT 7 | 8 | Nico Kreipke (nkreipke) 9 | 10 | 11 | LOCALIZATION 12 | 13 | English 14 | Vitor Marques de Miranda (vitor251093) 15 | 16 | English Revision 17 | Jean Baumgarten 18 | Paul Bertelink (PaulTheTall) 19 | 20 | Portuguese 21 | Vitor Marques de Miranda (vitor251093) 22 | 23 | Dutch 24 | Paul Bertelink (PaulTheTall) 25 | 26 | German 27 | Sascha Lamprecht (Sascha_77) 28 | Jean Baumgarten 29 | 30 | French 31 | Samuel Gauthier 32 | 33 | French Revision 34 | Jean Baumgarten 35 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | NSHumanReadableCopyright 22 | Copyright © 2017 VitorMM. All rights reserved. 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/NSApplication+Extension.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSApplication+Extension.h 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 23/12/2017. 6 | // Copyright © 2017 VitorMM. All rights reserved. 7 | // 8 | 9 | #ifndef NSApplication_Extension_Class 10 | #define NSApplication_Extension_Class 11 | 12 | #import 13 | #import "VMMComputerInformation.h" 14 | 15 | #define VMMAppearanceDarkPreMojaveCompatible IS_SYSTEM_MAC_OS_10_10_OR_SUPERIOR 16 | #define VMMAppearanceDarkCompatible IS_SYSTEM_MAC_OS_10_14_OR_SUPERIOR 17 | 18 | typedef NSString* VMMAppearanceName; 19 | 20 | static VMMAppearanceName _Nonnull const VMMAppearanceNameLight = @"NSAppearanceNameAqua"; 21 | static VMMAppearanceName _Nonnull const VMMAppearanceNameDarkPreMojave = @"NSAppearanceNameVibrantDark"; 22 | static VMMAppearanceName _Nonnull const VMMAppearanceNameDark = @"NSAppearanceNameDarkAqua"; 23 | 24 | @interface NSApplication (VMMApplication) 25 | 26 | +(void)restart; 27 | +(void)restartInLanguage:(nonnull NSString*)language; 28 | 29 | +(nullable VMMAppearanceName)appearance; 30 | +(BOOL)setAppearance:(nullable VMMAppearanceName)appearance; 31 | 32 | @end 33 | 34 | #endif 35 | 36 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/NSApplication+Extension.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSApplication+Extension.m 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 23/12/2017. 6 | // Copyright © 2017 VitorMM. All rights reserved. 7 | // 8 | 9 | #import "NSApplication+Extension.h" 10 | 11 | #import "NSBundle+Extension.h" 12 | #import "NSTask+Extension.h" 13 | #import "NSException+Extension.h" 14 | #import "VMMLogUtility.h" 15 | #import "VMMComputerInformation.h" 16 | 17 | @implementation NSApplication (VMMApplication) 18 | 19 | +(void)restart 20 | { 21 | [NSTask runProgram:@"open" withFlags:@[@"-n", [[NSBundle originalMainBundle] bundlePath]]]; 22 | exit(0); 23 | } 24 | 25 | +(void)restartInLanguage:(nonnull NSString*)language 26 | { 27 | if ([VMMComputerInformation isSystemMacOsEqualOrSuperiorTo:@"10.6.2"] == false) { 28 | // The '--args' parameter in 'open' was only introduced in macOS 10.6.2 29 | // Reference: https://superuser.com/a/116237 30 | 31 | @throw exception(NSIllegalSelectorException, @"NSApplication does not implement restartInLanguage:"); 32 | } 33 | 34 | if ([[NSLocale availableLocaleIdentifiers] containsObject:language] == false) { 35 | NSDebugLog(@"'%@' is not a valid locale identifier", language); 36 | return; 37 | } 38 | 39 | if ([[[NSBundle originalMainBundle] localizations] containsObject:language] == false) { 40 | NSDebugLog(@"That application does not support '%@'", language); 41 | return; 42 | } 43 | 44 | if ([[[NSBundle originalMainBundle] preferredLocalizations] containsObject:language]) { 45 | return; 46 | } 47 | 48 | NSTask *task = [[NSTask alloc] init]; 49 | [task setLaunchPath:@"/bin/sh"]; 50 | NSString *cmd = [NSString stringWithFormat:@"/usr/bin/open %@ %@ %@ %@ %@", 51 | @"-n", @"-a", [[[NSBundle originalMainBundle] bundlePath] stringByReplacingOccurrencesOfString:@" " withString:@"\\ "], 52 | @"--args", [NSString stringWithFormat:@"-AppleLanguages '(%@)'",language]]; 53 | [task setArguments:[NSArray arrayWithObjects:@"-c", cmd, nil]]; 54 | [task launch]; 55 | 56 | exit(0); 57 | } 58 | 59 | +(nullable VMMAppearanceName)appearance 60 | { 61 | if (VMMAppearanceDarkPreMojaveCompatible == false) { 62 | return nil; 63 | } 64 | 65 | NSAppearance* nsappearance = [NSApp appearance]; 66 | if (nsappearance == nil) { 67 | return nil; 68 | } 69 | 70 | return nsappearance.name; 71 | } 72 | +(BOOL)setAppearance:(nullable VMMAppearanceName)appearance 73 | { 74 | if (VMMAppearanceDarkPreMojaveCompatible == false) { 75 | return false; 76 | } 77 | 78 | @try { 79 | NSAppearance* nsappearance = appearance != nil ? [NSAppearance appearanceNamed:appearance] : nil; 80 | [NSApp setAppearance:nsappearance]; 81 | return true; 82 | } @catch (NSException *exception) { 83 | return false; 84 | } 85 | } 86 | 87 | @end 88 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/NSArray+Extension.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSArray+Extension.h 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 15/05/17. 6 | // Copyright © 2017 Vitor Marques de Miranda. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSArray (VMMArray) 12 | 13 | -(nonnull NSMutableArray*)map:(_Nullable id (^_Nonnull)(id _Nonnull object))newObjectForObject; 14 | -(nonnull NSMutableArray*)mapWithIndex:(_Nullable id (^_Nonnull)(id _Nonnull object, NSUInteger index))newObjectForObject; 15 | -(nonnull NSMutableArray*)filter:(BOOL (^_Nonnull)(id _Nonnull object))newObjectForObject; 16 | -(nonnull NSMutableArray*)filterWithIndex:(BOOL (^_Nonnull)(id _Nonnull object, NSUInteger index))newObjectForObject; 17 | -(nonnull instancetype)forEach:(void (^_Nonnull)(id _Nonnull object))newObjectForObject; 18 | 19 | -(nonnull NSArray*)arrayByRemovingRepetitions; 20 | -(nonnull NSArray*)arrayByRemovingObjectsFromArray:(nonnull NSArray*)otherArray; 21 | 22 | -(NSIndexSet* _Nonnull)indexesOfObject:(ObjectType _Nonnull)object inRange:(NSRange)range; 23 | -(NSIndexSet* _Nonnull)indexesOfObject:(ObjectType _Nonnull)object; 24 | 25 | -(NSInteger)lastIndexOfObject:(ObjectType _Nonnull)object inRange:(NSRange)range; 26 | 27 | -(void)differencesFromArray:(NSArray* _Nonnull)otherArray indexPaths:(void (^_Nonnull)(NSArray* _Nonnull addedIndexes, NSArray* _Nonnull removedIndexes))indexPaths; 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/NSArray+Extension.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSArray+Extension.m 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 15/05/17. 6 | // Copyright © 2017 Vitor Marques de Miranda. All rights reserved. 7 | // 8 | 9 | #import "NSArray+Extension.h" 10 | 11 | #import "NSMutableArray+Extension.h" 12 | 13 | @implementation NSArray (VMMArray) 14 | 15 | -(nonnull NSMutableArray*)map:(_Nullable id (^_Nonnull)(id _Nonnull object))newObjectForObject 16 | { 17 | return [[self mutableCopy] map:newObjectForObject]; 18 | } 19 | -(nonnull NSMutableArray*)mapWithIndex:(_Nullable id (^_Nonnull)(id _Nonnull object, NSUInteger index))newObjectForObject 20 | { 21 | return [[self mutableCopy] mapWithIndex:newObjectForObject]; 22 | } 23 | -(nonnull NSMutableArray*)filter:(BOOL (^_Nonnull)(id _Nonnull object))newObjectForObject 24 | { 25 | return [[self mutableCopy] filter:newObjectForObject]; 26 | } 27 | -(nonnull NSMutableArray*)filterWithIndex:(BOOL (^_Nonnull)(id _Nonnull object, NSUInteger index))newObjectForObject 28 | { 29 | return [[self mutableCopy] filterWithIndex:newObjectForObject]; 30 | } 31 | -(nonnull instancetype)forEach:(void (^_Nonnull)(id _Nonnull object))newObjectForObject 32 | { 33 | for (id object in self) { 34 | newObjectForObject(object); 35 | } 36 | return self; 37 | } 38 | 39 | -(nonnull NSArray*)arrayByRemovingRepetitions 40 | { 41 | return [NSSet setWithArray:self].allObjects; 42 | } 43 | 44 | -(nonnull NSArray*)arrayByRemovingObjectsFromArray:(nonnull NSArray*)otherArray 45 | { 46 | NSMutableArray* newArray = [self mutableCopy]; 47 | 48 | [newArray removeObjectsInArray:otherArray]; 49 | 50 | return newArray; 51 | } 52 | 53 | -(NSIndexSet* _Nonnull)indexesOfObject:(id _Nonnull)object inRange:(NSRange)range 54 | { 55 | return [self indexesOfObjectsPassingTest:^BOOL(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) 56 | { 57 | if (idx < range.location) return false; 58 | if (idx >= range.location + range.length) return false; 59 | return obj == object || [obj isEqual:object]; 60 | }]; 61 | } 62 | -(NSIndexSet* _Nonnull)indexesOfObject:(id _Nonnull)object 63 | { 64 | return [self indexesOfObjectsPassingTest:^BOOL(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) 65 | { 66 | return obj == object || [obj isEqual:object]; 67 | }]; 68 | } 69 | 70 | -(NSInteger)lastIndexOfObject:(id _Nonnull)object inRange:(NSRange)range 71 | { 72 | return (NSInteger)[self indexesOfObject:object inRange:range].lastIndex; 73 | } 74 | 75 | -(void)differencesFromArray:(NSArray* _Nonnull)otherArray indexPaths:(void (^_Nonnull)(NSArray* _Nonnull addedIndexes, NSArray* _Nonnull removedIndexes))indexPaths 76 | { 77 | NSMutableArray* removedIndexPaths = [[NSMutableArray alloc] init]; 78 | NSMutableArray* addedIndexPaths = [[NSMutableArray alloc] init]; 79 | NSInteger indexSelf = self.count - 1; 80 | NSInteger indexOther = otherArray.count - 1; 81 | 82 | while (indexSelf != -1 && indexOther != -1) 83 | { 84 | NSInteger nextSelfObjectInOther = [otherArray lastIndexOfObject:[self objectAtIndex:indexSelf] 85 | inRange:NSMakeRange(0, indexOther + 1)]; 86 | NSInteger nextOtherObjectInSelf = [self lastIndexOfObject:[otherArray objectAtIndex:indexOther] 87 | inRange:NSMakeRange(0, indexSelf + 1)]; 88 | 89 | if (nextOtherObjectInSelf == NSNotFound) 90 | { 91 | [addedIndexPaths addObject:[NSIndexSet indexSetWithIndex:indexSelf+1]]; 92 | indexOther -= 1; 93 | continue; 94 | } 95 | 96 | if (nextSelfObjectInOther == NSNotFound) 97 | { 98 | [removedIndexPaths addObject:[NSIndexSet indexSetWithIndex:indexSelf]]; 99 | indexSelf -= 1; 100 | continue; 101 | } 102 | 103 | if (nextOtherObjectInSelf != -1 && nextOtherObjectInSelf == indexSelf) 104 | { 105 | indexSelf -=1; 106 | indexOther -=1; 107 | continue; 108 | } 109 | } 110 | 111 | while (indexSelf != -1) 112 | { 113 | [removedIndexPaths addObject:[NSIndexSet indexSetWithIndex:indexSelf]]; 114 | indexSelf -= 1; 115 | } 116 | 117 | while (indexOther != -1) 118 | { 119 | [addedIndexPaths addObject:[NSIndexSet indexSetWithIndex:0]]; 120 | indexOther -= 1; 121 | } 122 | 123 | indexPaths(addedIndexPaths, removedIndexPaths); 124 | } 125 | 126 | 127 | @end 128 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/NSAttributedString+Extension.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSAttributedString+Extension.h 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 12/03/17. 6 | // Copyright © 2017 Vitor Marques de Miranda. All rights reserved. 7 | // 8 | 9 | #ifndef NSAttributedString_Extension_Class 10 | #define NSAttributedString_Extension_Class 11 | 12 | #import 13 | 14 | @interface NSAttributedString (VMMAttributedString) 15 | 16 | -(nullable instancetype)initWithHTMLData:(nonnull NSData*)data; 17 | -(nullable instancetype)initWithHTMLString:(nonnull NSString*)string; 18 | 19 | -(nonnull NSString*)htmlString; 20 | 21 | @end 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/NSAttributedString+Extension.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSAttributedString+Extension.m 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 12/03/17. 6 | // Copyright © 2017 Vitor Marques de Miranda. All rights reserved. 7 | // 8 | 9 | #import "NSAttributedString+Extension.h" 10 | 11 | @implementation NSAttributedString (VMMAttributedString) 12 | 13 | -(nullable instancetype)initWithHTMLData:(nonnull NSData*)data 14 | { 15 | self = [self initWithData:data options:@{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, 16 | NSCharacterEncodingDocumentAttribute:@(NSUTF8StringEncoding)} 17 | documentAttributes:nil error:nil]; 18 | return self; 19 | } 20 | -(nullable instancetype)initWithHTMLString:(nonnull NSString*)string 21 | { 22 | self = [self initWithHTMLData:[string dataUsingEncoding:NSUTF8StringEncoding]]; 23 | return self; 24 | } 25 | 26 | -(nonnull NSString*)htmlString 27 | { 28 | NSString* htmlString; 29 | 30 | @autoreleasepool 31 | { 32 | NSDictionary *documentAttributes = @{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType}; 33 | NSData *htmlData = [self dataFromRange:NSMakeRange(0, self.length) documentAttributes:documentAttributes error:NULL]; 34 | htmlString = [[NSString alloc] initWithData:htmlData encoding:NSUTF8StringEncoding]; 35 | 36 | // That solves the double-line bug 37 | htmlString = [htmlString stringByReplacingOccurrencesOfString:@"
" withString:@""]; 38 | } 39 | 40 | return htmlString; 41 | } 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/NSBundle+Extension.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSBundle+Extension.h 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 25/11/2017. 6 | // Copyright © 2017 VitorMM. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSBundle (VMMBundle) 12 | 13 | -(nonnull NSUserDefaults*)userDefaults; 14 | 15 | -(nonnull NSString*)bundleName; 16 | -(nullable NSImage*)bundleIcon; 17 | 18 | -(BOOL)isAppTranslocationActive; 19 | -(BOOL)disableAppTranslocation; 20 | 21 | +(nullable NSBundle*)originalMainBundle; 22 | 23 | -(BOOL)preferExternalGPU; 24 | -(void)setPreferExternalGPU:(BOOL)prefer; 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/NSColor+Extension.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSColor+Extension.h 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 31/08/17. 6 | // Copyright © 2017 Vitor Marques de Miranda. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NSColor* _Nullable RGBA(CGFloat r, CGFloat g, CGFloat b, CGFloat a); 12 | NSColor* _Nullable RGB(CGFloat r, CGFloat g, CGFloat b); 13 | 14 | @interface NSColor (VMMColor) 15 | 16 | +(nullable NSColor*)colorWithHexColorString:(nonnull NSString*)inColorString; 17 | -(nullable NSString*)hexColorString; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/NSColor+Extension.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSColor+Extension.m 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 31/08/17. 6 | // Copyright © 2017 Vitor Marques de Miranda. All rights reserved. 7 | // 8 | 9 | #import "NSColor+Extension.h" 10 | #import "NSException+Extension.h" 11 | 12 | NSColor* _Nullable RGBA(CGFloat r, CGFloat g, CGFloat b, CGFloat a) 13 | { 14 | return [NSColor colorWithDeviceRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:a/255.0]; 15 | } 16 | 17 | NSColor* _Nullable RGB(CGFloat r, CGFloat g, CGFloat b) 18 | { 19 | return RGBA(r,g,b,255.0); 20 | } 21 | 22 | @implementation NSColor (VMMColor) 23 | 24 | +(nullable NSColor*)colorWithHexColorString:(nonnull NSString*)inColorString 25 | { 26 | NSColor* result = nil; 27 | 28 | @autoreleasepool 29 | { 30 | unsigned colorCode = 0; 31 | unsigned char redByte, greenByte, blueByte; 32 | 33 | if (inColorString.length == 7 && [inColorString hasPrefix:@"#"]) 34 | { 35 | inColorString = [inColorString substringFromIndex:1]; 36 | } 37 | 38 | if (inColorString.length != 6) 39 | { 40 | @throw exception(NSInvalidArgumentException, 41 | @"colorWithHexColorString: only accepts hexadecimal colors, with 6 or 7 characters (eg. 000000 or #000000)"); 42 | } 43 | 44 | NSScanner* scanner = [NSScanner scannerWithString:inColorString]; 45 | (void) [scanner scanHexInt:&colorCode]; // ignore error 46 | 47 | redByte = (unsigned char)(colorCode >> 16); 48 | greenByte = (unsigned char)(colorCode >> 8); 49 | blueByte = (unsigned char)(colorCode); // masks off high bits 50 | 51 | result = RGB((CGFloat)redByte, (CGFloat)greenByte, (CGFloat)blueByte); 52 | } 53 | 54 | return result; 55 | } 56 | -(nullable NSString*)hexColorString 57 | { 58 | NSString* result = nil; 59 | 60 | @autoreleasepool 61 | { 62 | // https://developer.apple.com/library/content/qa/qa1576/_index.html 63 | 64 | NSString *redHexValue, *greenHexValue, *blueHexValue; 65 | CGFloat redFloatValue, greenFloatValue, blueFloatValue; 66 | int redIntValue, greenIntValue, blueIntValue; 67 | 68 | NSColor *convertedColor = [self colorUsingColorSpaceName:NSCalibratedRGBColorSpace]; 69 | 70 | if (convertedColor != nil) 71 | { 72 | [convertedColor getRed:&redFloatValue green:&greenFloatValue blue:&blueFloatValue alpha:NULL]; 73 | 74 | redIntValue = redFloatValue * 255.99999f; 75 | greenIntValue = greenFloatValue * 255.99999f; 76 | blueIntValue = blueFloatValue * 255.99999f; 77 | 78 | redHexValue = [NSString stringWithFormat:@"%02x", redIntValue]; 79 | greenHexValue = [NSString stringWithFormat:@"%02x", greenIntValue]; 80 | blueHexValue = [NSString stringWithFormat:@"%02x", blueIntValue]; 81 | 82 | result = [NSString stringWithFormat:@"%@%@%@", redHexValue, greenHexValue, blueHexValue]; 83 | } 84 | } 85 | 86 | return result; 87 | } 88 | 89 | @end 90 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/NSData+Extension.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSData+Extension.h 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 22/02/17. 6 | // Copyright © 2017 Vitor Marques de Miranda. All rights reserved. 7 | // 8 | 9 | #ifndef NSData_Extension_Class 10 | #define NSData_Extension_Class 11 | 12 | #import 13 | 14 | @interface NSData (VMMData) 15 | 16 | +(void)dataWithContentsOfURL:(nonnull NSURL *)url timeoutInterval:(long long int)timeoutInterval withCompletionHandler:(void (^_Nullable)(NSUInteger statusCode, NSData* _Nullable data, NSError* _Nullable error))completion; 17 | +(nullable NSData*)safeDataWithContentsOfFile:(nonnull NSString*)filePath; 18 | 19 | +(nullable NSString*)jsonStringWithObject:(nonnull id)object; 20 | +(nullable NSData*)jsonDataWithObject:(nonnull id)object; 21 | -(nullable id)objectWithJsonData; 22 | 23 | -(nonnull NSString*)base64EncodedString; 24 | 25 | @end 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/NSData+Extension.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSData+Extension.m 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 22/02/17. 6 | // Copyright © 2017 Vitor Marques de Miranda. All rights reserved. 7 | // 8 | 9 | #import "NSData+Extension.h" 10 | 11 | #import "SZJsonParser.h" 12 | 13 | #import "VMMAlert.h" 14 | #import "NSMutableString+Extension.h" 15 | 16 | #import "VMMComputerInformation.h" 17 | #import "VMMLocalizationUtility.h" 18 | 19 | @implementation NSData (VMMData) 20 | 21 | +(void)dataWithContentsOfURL:(nonnull NSURL *)url timeoutInterval:(long long int)timeoutInterval withCompletionHandler:(void (^_Nullable)(NSUInteger statusCode, NSData* _Nullable data, NSError* _Nullable error))completion 22 | { 23 | NSData* stringData; 24 | 25 | @autoreleasepool 26 | { 27 | NSURLRequest* request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalCacheData 28 | timeoutInterval:timeoutInterval]; 29 | 30 | NSError *error = nil; 31 | NSHTTPURLResponse *response = nil; 32 | stringData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error]; 33 | 34 | if (completion != nil) { 35 | completion(response.statusCode, stringData, error); 36 | } 37 | } 38 | } 39 | +(nullable NSData*)safeDataWithContentsOfFile:(nonnull NSString*)filePath 40 | { 41 | if (![[NSFileManager defaultManager] fileExistsAtPath:filePath]) return nil; 42 | 43 | NSData* data; 44 | 45 | @autoreleasepool 46 | { 47 | NSError *error = nil; 48 | data = [[NSData alloc] initWithContentsOfFile:filePath options:0 error:&error]; 49 | 50 | if (error != nil) 51 | { 52 | [VMMAlert showAlertOfType:VMMAlertTypeError withMessage:[NSString stringWithFormat:VMMLocalizedString(@"Error while loading file data: %@"), error.localizedDescription]]; 53 | } 54 | } 55 | 56 | return data; 57 | } 58 | 59 | +(nullable NSString*)jsonStringWithObject:(nonnull id)object 60 | { 61 | if (IsClassNSJSONSerializationAvailable == false) 62 | { 63 | @autoreleasepool 64 | { 65 | if ([object isKindOfClass:[NSString class]]) 66 | { 67 | NSMutableString* stringObject = [(NSString*)object mutableCopy]; 68 | [stringObject replaceOccurrencesOfString:@"\"" withString:@"\\\""]; 69 | [stringObject replaceOccurrencesOfString:@"\n" withString:@"\\\n"]; 70 | [stringObject replaceOccurrencesOfString:@"/" withString:@"\\/" ]; 71 | return [NSString stringWithFormat:@"\"%@\"",stringObject]; 72 | } 73 | 74 | if ([object isKindOfClass:[NSArray class]]) 75 | { 76 | NSMutableArray* array = [[NSMutableArray alloc] init]; 77 | for (id innerObject in (NSArray*)object) 78 | { 79 | [array addObject:[self jsonStringWithObject:innerObject]]; 80 | } 81 | return [NSString stringWithFormat:@"[%@]",[array componentsJoinedByString:@","]]; 82 | } 83 | 84 | if ([object isKindOfClass:[NSDictionary class]]) 85 | { 86 | NSMutableArray* dict = [[NSMutableArray alloc] init]; 87 | for (NSString* key in [(NSDictionary*)object allKeys]) 88 | { 89 | [dict addObject:[NSString stringWithFormat:@"%@:%@",[self jsonStringWithObject:key], 90 | [self jsonStringWithObject:[(NSDictionary*)object objectForKey:key]]]]; 91 | } 92 | return [NSString stringWithFormat:@"{%@}",[dict componentsJoinedByString:@","]]; 93 | } 94 | 95 | if ([object isKindOfClass:[NSNumber class]]) 96 | { 97 | NSInteger integerValue = [(NSNumber*)object integerValue]; 98 | double doubleValue = [(NSNumber*)object doubleValue]; 99 | BOOL boolValue = [(NSNumber*)object boolValue]; 100 | 101 | if (integerValue != doubleValue) return [NSString stringWithFormat:@"%lf",doubleValue]; 102 | if (integerValue != boolValue) return [NSString stringWithFormat:@"%ld",integerValue]; 103 | return boolValue ? @"true" : @"false"; 104 | } 105 | 106 | return @""; 107 | } 108 | } 109 | 110 | return [[NSString alloc] initWithData:[self jsonDataWithObject:object] encoding:NSUTF8StringEncoding]; 111 | } 112 | 113 | +(nullable NSData*)jsonDataWithObject:(nonnull id)object 114 | { 115 | if (IsClassNSJSONSerializationAvailable == false) 116 | { 117 | @autoreleasepool 118 | { 119 | return [[self jsonStringWithObject:object] dataUsingEncoding:NSUTF8StringEncoding]; 120 | } 121 | } 122 | 123 | return [NSJSONSerialization dataWithJSONObject:object options:NSJSONWritingPrettyPrinted error:nil]; 124 | } 125 | 126 | -(nullable id)objectWithJsonData 127 | { 128 | if (IsClassNSJSONSerializationAvailable == false) 129 | { 130 | @autoreleasepool 131 | { 132 | @try 133 | { 134 | return [[[NSString alloc] initWithData:self encoding:NSUTF8StringEncoding] jsonObject]; 135 | } 136 | @catch (NSException* exception) 137 | { 138 | return nil; 139 | } 140 | } 141 | } 142 | 143 | return [NSJSONSerialization JSONObjectWithData:self options:0 error:nil]; 144 | } 145 | 146 | -(nonnull NSString*)base64EncodedString 147 | { 148 | if (![self respondsToSelector:@selector(base64EncodedStringWithOptions:)]) 149 | { 150 | return [self base64Encoding]; 151 | } 152 | 153 | return [self base64EncodedStringWithOptions:0]; 154 | } 155 | 156 | @end 157 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/NSDateFormatter+Extension.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSDateFormatter+Extension.h 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 21/07/17. 6 | // Copyright © 2017 Vitor Marques de Miranda. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSDateFormatter (VMMDateFormatter) 12 | 13 | +(nullable NSDate*)dateFromString:(nonnull NSString *)string withFormat:(nonnull NSString*)format; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/NSDateFormatter+Extension.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSDateFormatter+Extension.m 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 21/07/17. 6 | // Copyright © 2017 Vitor Marques de Miranda. All rights reserved. 7 | // 8 | 9 | #import "NSDateFormatter+Extension.h" 10 | 11 | @implementation NSDateFormatter (VMMDateFormatter) 12 | 13 | +(nullable NSDate*)dateFromString:(nonnull NSString *)string withFormat:(nonnull NSString*)format 14 | { 15 | NSDateFormatter *df = [[NSDateFormatter alloc] init]; 16 | [df setDateFormat:format]; 17 | return [df dateFromString:string]; 18 | } 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/NSException+Extension.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSException+Extension.h 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 19/12/2017. 6 | // Copyright © 2017 VitorMM. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NSException* exception(NSString* name, NSString* reason); 12 | 13 | @interface NSException (VMMException) 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/NSException+Extension.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSException+Extension.m 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 19/12/2017. 6 | // Copyright © 2017 VitorMM. All rights reserved. 7 | // 8 | 9 | #import "NSException+Extension.h" 10 | 11 | NSException* exception(NSString* name, NSString* reason) 12 | { 13 | return [NSException exceptionWithName:name reason:reason userInfo:nil]; 14 | } 15 | 16 | @implementation NSException (VMMException) 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/NSFileManager+Extension.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSFileManager+Extension.h 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 22/02/17. 6 | // Copyright © 2017 Vitor Marques de Miranda. All rights reserved. 7 | // 8 | 9 | #ifndef NSFileManager_Extension_Class 10 | #define NSFileManager_Extension_Class 11 | 12 | #import 13 | 14 | typedef enum NSChecksumType 15 | { 16 | NSChecksumTypeGOSTMac, 17 | NSChecksumTypeStreebog512, 18 | NSChecksumTypeStreebog256, 19 | NSChecksumTypeGOST94, 20 | NSChecksumTypeMD4, 21 | NSChecksumTypeMD5, 22 | NSChecksumTypeRIPEMD160, 23 | NSChecksumTypeSHA, 24 | NSChecksumTypeSHA1, 25 | NSChecksumTypeSHA224, 26 | NSChecksumTypeSHA256, 27 | NSChecksumTypeSHA384, 28 | NSChecksumTypeSHA512, 29 | NSChecksumTypeWrirlpool 30 | } NSChecksumType; 31 | 32 | @interface NSFileManager (VMMFileManager) 33 | 34 | -(BOOL)createSymbolicLinkAtPath:(nonnull NSString *)path withDestinationPath:(nonnull NSString *)destPath; 35 | -(BOOL)createDirectoryAtPath:(nonnull NSString*)path withIntermediateDirectories:(BOOL)interDirs; 36 | -(BOOL)createEmptyFileAtPath:(nonnull NSString*)path; 37 | 38 | -(BOOL)moveItemAtPath:(nonnull NSString*)path toPath:(nonnull NSString*)destination; 39 | -(BOOL)copyItemAtPath:(nonnull NSString*)path toPath:(nonnull NSString*)destination; 40 | -(BOOL)removeItemAtPath:(nonnull NSString*)path; 41 | -(BOOL)directoryExistsAtPath:(nonnull NSString*)path; 42 | -(BOOL)regularFileExistsAtPath:(nonnull NSString*)path; 43 | -(nullable NSArray*)contentsOfDirectoryAtPath:(nonnull NSString*)path; 44 | -(nullable NSArray*)subpathsAtPath:(nonnull NSString *)path ofFilesNamed:(nonnull NSString*)fileName; 45 | -(nullable NSString*)destinationOfSymbolicLinkAtPath:(nonnull NSString *)path; 46 | 47 | -(nullable NSString*)userReadablePathForItemAtPath:(nonnull NSString*)path joinedByString:(nullable NSString*)join; 48 | 49 | -(unsigned long long int)sizeOfRegularFileAtPath:(nonnull NSString*)path; 50 | -(unsigned long long int)sizeOfDirectoryAtPath:(nonnull NSString*)path; 51 | 52 | -(nullable NSString*)checksum:(NSChecksumType)checksum ofFileAtPath:(nonnull NSString*)file; 53 | 54 | -(nullable NSString*)base64OfFileAtPath:(nonnull NSString*)path; 55 | 56 | @end 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/NSImage+Extension.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSImage+Extension.h 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 12/03/17. 6 | // Copyright © 2017 Vitor Marques de Miranda. All rights reserved. 7 | // 8 | 9 | #ifndef NSImage_Extension_Class 10 | #define NSImage_Extension_Class 11 | 12 | #import 13 | 14 | @interface NSBitmapImageRep (VMMBitmapImageRep) 15 | 16 | -(BOOL)isTransparentAtX:(int)x andY:(int)y; 17 | 18 | @end 19 | 20 | 21 | @interface NSImage (VMMImage) 22 | 23 | +(NSImage*)imageWithData:(NSData*)data; 24 | 25 | +(NSImage*)quickLookImageWithMaximumSize:(int)size forFileAtPath:(NSString*)arquivo; 26 | +(NSImage*)imageFromFileAtPath:(NSString*)arquivo; 27 | 28 | +(NSImage*)transparentImageWithSize:(NSSize)size; 29 | 30 | -(BOOL)isTransparent; 31 | 32 | -(BOOL)saveAsIcnsAtPath:(NSString*)icnsPath; 33 | 34 | -(NSData*)dataForImageWithType:(NSBitmapImageFileType)type; 35 | -(BOOL)writeToFile:(NSString*)file atomically:(BOOL)useAuxiliaryFile; 36 | 37 | @end 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/NSMenuItem+Extension.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSMenuItem+Extension.h 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 30/05/17. 6 | // Copyright © 2017 Vitor Marques de Miranda. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSMenuItem (VMMMenuItem) 12 | 13 | +(nonnull NSMenuItem*)menuItemWithTitle:(nonnull NSString*)title andAction:(nullable SEL)action forTarget:(nullable id)target; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/NSMenuItem+Extension.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSMenuItem+Extension.m 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 30/05/17. 6 | // Copyright © 2017 Vitor Marques de Miranda. All rights reserved. 7 | // 8 | 9 | #import "NSMenuItem+Extension.h" 10 | 11 | @implementation NSMenuItem (VMMMenuItem) 12 | 13 | +(nonnull NSMenuItem*)menuItemWithTitle:(nonnull NSString*)title andAction:(nullable SEL)action forTarget:(nullable id)target 14 | { 15 | NSMenuItem* item = [[NSMenuItem alloc] initWithTitle:title action:action keyEquivalent:@""]; 16 | [item setTarget:target]; 17 | return item; 18 | } 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/NSMutableArray+Extension.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSMutableArray+Extension.h 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 24/07/2017. 6 | // Copyright © 2017 Vitor Marques de Miranda. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSMutableArray (VMMMutableArray) 12 | 13 | -(nonnull NSMutableArray*)map:(_Nullable id (^_Nonnull)(id _Nonnull object))newObjectForObject; 14 | -(nonnull NSMutableArray*)mapWithIndex:(_Nullable id (^_Nonnull)(id _Nonnull object, NSUInteger index))newObjectForObject; 15 | -(nonnull NSMutableArray*)filter:(BOOL (^_Nonnull)(id _Nonnull object))newObjectForObject; 16 | -(nonnull NSMutableArray*)filterWithIndex:(BOOL (^_Nonnull)(id _Nonnull object, NSUInteger index))newObjectForObject; 17 | 18 | -(void)sortAlphabeticallyByKey:(nonnull NSString*)key ascending:(BOOL)ascending; 19 | -(void)sortAlphabeticallyAscending:(BOOL)ascending; 20 | -(void)sortDictionariesWithKey:(nonnull NSString *)key orderingByValuesOrder:(nonnull NSArray*)value; 21 | -(void)sortBySelector:(SEL _Nonnull)selector inOrder:(NSArray* _Nonnull)order; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/NSMutableArray+Extension.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSMutableArray+Extension.m 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 24/07/2017. 6 | // Copyright © 2017 Vitor Marques de Miranda. All rights reserved. 7 | // 8 | 9 | #import "NSMutableArray+Extension.h" 10 | 11 | @implementation NSMutableArray (VMMMutableArray) 12 | 13 | -(nonnull NSMutableArray*)map:(_Nullable id (^_Nonnull)(id _Nonnull object))newObjectForObject 14 | { 15 | for (NSUInteger index = 0; index < self.count; index++) 16 | { 17 | id newObject = newObjectForObject([self objectAtIndex:index]); 18 | [self replaceObjectAtIndex:index withObject:newObject ? newObject : [NSNull null]]; 19 | } 20 | return self; 21 | } 22 | -(nonnull NSMutableArray*)mapWithIndex:(_Nullable id (^_Nonnull)(id _Nonnull object, NSUInteger index))newObjectForObject 23 | { 24 | for (NSUInteger index = 0; index < self.count; index++) 25 | { 26 | id newObject = newObjectForObject([self objectAtIndex:index], index); 27 | [self replaceObjectAtIndex:index withObject:newObject ? newObject : [NSNull null]]; 28 | } 29 | return self; 30 | } 31 | -(nonnull NSMutableArray*)filter:(BOOL (^_Nonnull)(id _Nonnull object))newObjectForObject 32 | { 33 | NSUInteger size = self.count; 34 | for (NSUInteger index = 0; index < size; index++) 35 | { 36 | BOOL preserve = newObjectForObject([self objectAtIndex:index]); 37 | if (!preserve) { 38 | [self removeObjectAtIndex:index]; 39 | index--; 40 | size--; 41 | } 42 | } 43 | return self; 44 | } 45 | -(nonnull NSMutableArray*)filterWithIndex:(BOOL (^_Nonnull)(id _Nonnull object, NSUInteger index))newObjectForObject 46 | { 47 | NSUInteger size = self.count; 48 | for (NSUInteger index = 0; index < size; index++) 49 | { 50 | BOOL preserve = newObjectForObject([self objectAtIndex:index], index); 51 | if (!preserve) { 52 | [self removeObjectAtIndex:index]; 53 | index--; 54 | size--; 55 | } 56 | } 57 | return self; 58 | } 59 | 60 | -(void)sortAlphabeticallyByKey:(nonnull NSString*)key ascending:(BOOL)ascending 61 | { 62 | NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:key ascending:ascending selector:@selector(caseInsensitiveCompare:)]; 63 | [self sortUsingDescriptors:@[sort]]; 64 | } 65 | -(void)sortAlphabeticallyAscending:(BOOL)ascending 66 | { 67 | NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:nil ascending:ascending selector:@selector(caseInsensitiveCompare:)]; 68 | [self sortUsingDescriptors:@[sort]]; 69 | } 70 | -(void)sortDictionariesWithKey:(nonnull NSString *)key orderingByValuesOrder:(nonnull NSArray*)value 71 | { 72 | [self sortUsingComparator:^NSComparisonResult(NSDictionary* obj1, NSDictionary* obj2) 73 | { 74 | NSUInteger obj1ValueIndex = obj1[key] != nil ? [value indexOfObject:obj1[key]] : -1; 75 | NSUInteger obj2ValueIndex = obj2[key] != nil ? [value indexOfObject:obj2[key]] : -1; 76 | 77 | if (obj1ValueIndex == -1 && obj2ValueIndex != -1) return NSOrderedDescending; 78 | if (obj1ValueIndex != -1 && obj2ValueIndex == -1) return NSOrderedAscending; 79 | if (obj1ValueIndex == -1 && obj2ValueIndex == -1) return NSOrderedSame; 80 | 81 | if (obj1ValueIndex > obj2ValueIndex) return NSOrderedDescending; 82 | if (obj1ValueIndex < obj2ValueIndex) return NSOrderedAscending; 83 | return NSOrderedSame; 84 | }]; 85 | } 86 | 87 | -(void)sortBySelector:(SEL _Nonnull)selector inOrder:(NSArray* _Nonnull)order 88 | { 89 | [self sortUsingComparator:^NSComparisonResult(id _Nonnull obj1, id _Nonnull obj2) 90 | { 91 | NSUInteger obj1ValueIndex = -1; 92 | NSUInteger obj2ValueIndex = -1; 93 | 94 | #pragma clang diagnostic push 95 | #pragma clang diagnostic ignored "-Warc-performSelector-leaks" 96 | if ([obj1 respondsToSelector:selector]) 97 | { 98 | id obj1ReturnedValue = [obj1 performSelector:selector]; 99 | if (obj1ReturnedValue != nil) obj1ValueIndex = [order indexOfObject:obj1ReturnedValue]; 100 | } 101 | 102 | if ([obj2 respondsToSelector:selector]) 103 | { 104 | id obj2ReturnedValue = [obj2 performSelector:selector]; 105 | if (obj2ReturnedValue != nil) obj2ValueIndex = [order indexOfObject:obj2ReturnedValue]; 106 | } 107 | #pragma clang diagnostic pop 108 | 109 | if (obj1ValueIndex == -1 && obj2ValueIndex != -1) return NSOrderedDescending; 110 | if (obj1ValueIndex != -1 && obj2ValueIndex == -1) return NSOrderedAscending; 111 | if (obj1ValueIndex == -1 && obj2ValueIndex == -1) return NSOrderedSame; 112 | 113 | if (obj1ValueIndex > obj2ValueIndex) return NSOrderedDescending; 114 | if (obj1ValueIndex < obj2ValueIndex) return NSOrderedAscending; 115 | return NSOrderedSame; 116 | }]; 117 | } 118 | 119 | 120 | @end 121 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/NSMutableAttributedString+Extension.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSMutableAttributedString+Extension.h 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 22/02/17. 6 | // Copyright © 2017 Vitor Marques de Miranda. All rights reserved. 7 | // 8 | 9 | #ifndef NSMutableAttributedString_Extension_Class 10 | #define NSMutableAttributedString_Extension_Class 11 | 12 | #import 13 | 14 | @interface NSMutableAttributedString (VMMMutableAttributedString) 15 | 16 | -(instancetype)initWithString:(NSString*)str fontNamed:(NSString*)fontName size:(CGFloat)size; 17 | 18 | -(void)replaceOccurrencesOfString:(NSString*)oldString withString:(NSString*)newString; 19 | 20 | -(void)addAttribute:(NSString *)name value:(id)value; 21 | -(void)setRegularFont:(NSString*)regFont boldFont:(NSString*)boldFont italicFont:(NSString*)italicFont boldAndItalicFont:(NSString*)biFont size:(CGFloat)fontSize; 22 | 23 | -(void)setTextJustified; 24 | -(void)setTextAlignment:(NSTextAlignment)textAlignment; 25 | 26 | -(void)setFontColor:(NSColor*)color range:(NSRange)range; 27 | -(void)setFontColor:(NSColor*)color; 28 | -(void)setFont:(NSFont*)font range:(NSRange)range; 29 | -(void)setFont:(NSFont*)font; 30 | 31 | -(void)appendString:(NSString*)aString; 32 | 33 | -(BOOL)adjustExpansionToFitWidth:(CGFloat)width; 34 | 35 | @end 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/NSMutableAttributedString+Extension.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSMutableAttributedString+Extension.m 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 22/02/17. 6 | // Copyright © 2017 Vitor Marques de Miranda. All rights reserved. 7 | // 8 | 9 | #import "NSMutableAttributedString+Extension.h" 10 | 11 | #import "VMMComputerInformation.h" 12 | 13 | @implementation NSMutableAttributedString (VMMMutableAttributedString) 14 | 15 | -(instancetype)initWithString:(NSString*)str fontNamed:(NSString*)fontName size:(CGFloat)size 16 | { 17 | self = [self initWithString:str]; 18 | 19 | if (self) 20 | { 21 | NSFont* font = [NSFont fontWithName:fontName size:size]; 22 | [self addAttribute:NSFontAttributeName value:font]; 23 | } 24 | 25 | return self; 26 | } 27 | 28 | -(void)replaceOccurrencesOfString:(NSString*)oldString withString:(NSString*)newString 29 | { 30 | NSRange downloadRange = [self.string rangeOfString:oldString]; 31 | while (downloadRange.location != NSNotFound && downloadRange.length != 0) 32 | { 33 | [self replaceCharactersInRange:downloadRange withString:newString]; 34 | downloadRange = [self.string rangeOfString:oldString]; 35 | } 36 | } 37 | 38 | -(void)addAttribute:(NSString *)name value:(id)value 39 | { 40 | [self addAttribute:name value:value range:NSMakeRange(0, self.length)]; 41 | } 42 | -(void)setRegularFont:(NSString*)regFont boldFont:(NSString*)boldFont italicFont:(NSString*)italicFont boldAndItalicFont:(NSString*)biFont size:(CGFloat)fontSize 43 | { 44 | @autoreleasepool 45 | { 46 | NSMutableDictionary* fontBoldDictionary = [[NSMutableDictionary alloc] init]; 47 | NSMutableDictionary* fontItalicDictionary = [[NSMutableDictionary alloc] init]; 48 | 49 | for (int i=0; i< self.length; i++) 50 | { 51 | NSString *fontName = [[self attribute:NSFontAttributeName atIndex:i effectiveRange:nil] fontName]; 52 | 53 | NSNumber* hasItalic = fontItalicDictionary[fontName]; 54 | if (hasItalic == nil) 55 | { 56 | fontItalicDictionary[fontName] = @([[[NSFontManager alloc] init] fontNamed:fontName hasTraits:NSItalicFontMask]); 57 | hasItalic = fontItalicDictionary[fontName]; 58 | } 59 | 60 | NSNumber* hasBold = fontBoldDictionary[fontName]; 61 | if (hasBold == nil) 62 | { 63 | fontBoldDictionary[fontName] = @([[[NSFontManager alloc] init] fontNamed:fontName hasTraits:NSBoldFontMask]); 64 | hasBold = fontBoldDictionary[fontName]; 65 | } 66 | 67 | fontName = regFont; 68 | if (boldFont && hasBold.boolValue) fontName = boldFont; 69 | if (italicFont && hasItalic.boolValue) fontName = italicFont; 70 | if (biFont && hasBold.boolValue && hasItalic.boolValue) fontName = biFont; 71 | 72 | [self setFont:[NSFont fontWithName:fontName size:fontSize] range:NSMakeRange(i,1)]; 73 | } 74 | } 75 | } 76 | 77 | -(void)setTextJustified 78 | { 79 | [self setTextAlignment:IS_SYSTEM_MAC_OS_10_11_OR_SUPERIOR ? NSTextAlignmentJustified : NSJustifiedTextAlignment]; 80 | } 81 | -(void)setTextAlignment:(NSTextAlignment)textAlignment 82 | { 83 | NSMutableParagraphStyle *paragrapStyle = [[NSMutableParagraphStyle alloc] init]; 84 | paragrapStyle.alignment = textAlignment; 85 | [self addAttribute:NSParagraphStyleAttributeName value:paragrapStyle]; 86 | } 87 | 88 | -(void)setFontColor:(NSColor*)color range:(NSRange)range 89 | { 90 | [self addAttribute:NSForegroundColorAttributeName value:color range:range]; 91 | } 92 | -(void)setFontColor:(NSColor*)color 93 | { 94 | [self addAttribute:NSForegroundColorAttributeName value:color]; 95 | } 96 | -(void)setFont:(NSFont*)font range:(NSRange)range 97 | { 98 | [self addAttribute:NSFontAttributeName value:font range:range]; 99 | } 100 | -(void)setFont:(NSFont*)font 101 | { 102 | [self addAttribute:NSFontAttributeName value:font]; 103 | } 104 | 105 | -(void)appendString:(NSString*)aString 106 | { 107 | [self appendAttributedString:[[NSAttributedString alloc] initWithString:aString]]; 108 | } 109 | 110 | -(BOOL)adjustExpansionToFitWidth:(CGFloat)width 111 | { 112 | CGFloat originalWidth = self.size.width; 113 | 114 | BOOL sizeChanged = false; 115 | CGFloat resizeRate = 0.0; 116 | 117 | if (originalWidth > width) 118 | { 119 | sizeChanged = true; 120 | resizeRate = 1 - originalWidth/width; 121 | } 122 | 123 | [self addAttribute:NSExpansionAttributeName value:@(resizeRate)]; 124 | return sizeChanged; 125 | } 126 | 127 | @end 128 | 129 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/NSMutableDictionary+Extension.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSMutableDictionary+Extension.h 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 22/07/16. 6 | // Copyright © 2016 Vitor Marques de Miranda. All rights reserved. 7 | // 8 | 9 | #ifndef NSMutableDictionary_Extension_Class 10 | #define NSMutableDictionary_Extension_Class 11 | 12 | #import 13 | 14 | @interface NSMutableDictionary (VMMMutableDictionary) 15 | 16 | +(nullable instancetype)mutableDictionaryWithContentsOfFile:(nonnull NSString*)filePath; 17 | 18 | @end 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/NSMutableDictionary+Extension.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSExtensions.m 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 22/07/16. 6 | // Copyright © 2016 Vitor Marques de Miranda. All rights reserved. 7 | // 8 | 9 | #import "NSMutableDictionary+Extension.h" 10 | 11 | @implementation NSMutableDictionary (VMMMutableDictionary) 12 | 13 | +(nullable instancetype)mutableDictionaryWithContentsOfFile:(nonnull NSString*)filePath 14 | { 15 | NSMutableDictionary *dictionary; 16 | 17 | @try 18 | { 19 | dictionary = [[NSMutableDictionary alloc] initWithContentsOfFile:filePath]; 20 | } 21 | @catch (NSException *exception) 22 | { 23 | return nil; 24 | } 25 | 26 | return dictionary; 27 | } 28 | 29 | @end 30 | 31 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/NSMutableString+Extension.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSMutableString+Extension.h 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 04/11/2017. 6 | // Copyright © 2017 VitorMM. All rights reserved. 7 | // 8 | 9 | #ifndef NSMutableString_Extension_Class 10 | #define NSMutableString_Extension_Class 11 | 12 | #import 13 | 14 | @interface NSMutableString (VMMMutableString) 15 | 16 | -(void)replaceOccurrencesOfString:(nonnull NSString *)target withString:(nonnull NSString *)replacement; 17 | 18 | -(void)replaceOccurrencesOfRegex:(nonnull NSString *)target withString:(nonnull NSString *)replacement; 19 | 20 | -(nonnull NSMutableString*)trim; 21 | 22 | @end 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/NSMutableString+Extension.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSMutableString+Extension.m 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 04/11/2017. 6 | // Copyright © 2017 VitorMM. All rights reserved. 7 | // 8 | 9 | #import "NSMutableString+Extension.h" 10 | #import "NSString+Extension.h" 11 | 12 | @implementation NSMutableString (VMMMutableString) 13 | 14 | -(void)replaceOccurrencesOfString:(nonnull NSString *)target withString:(nonnull NSString *)replacement 15 | { 16 | [self replaceOccurrencesOfString:target withString:replacement options:0 range:NSMakeRange(0, self.length)]; 17 | } 18 | 19 | -(void)replaceOccurrencesOfRegex:(nonnull NSString *)target withString:(nonnull NSString *)replacement 20 | { 21 | NSRange range = NSMakeRange(0, self.length); 22 | NSArray* matches = [self componentsMatchingWithRegex:target]; 23 | for (NSString* match in matches) { 24 | [self replaceOccurrencesOfString:match withString:replacement options:0 range:range]; 25 | } 26 | } 27 | 28 | -(nonnull NSMutableString*)trim 29 | { 30 | // We used to use the method below, but the method in use today is about 2 to 5 times faster 31 | 32 | // while ([self hasPrefix:@" "] || [self hasPrefix:@"\n"] || [self hasPrefix:@"\t"]) 33 | // [self replaceCharactersInRange:NSMakeRange(0, 1) withString:@""]; 34 | // while ([self hasSuffix:@" "] || [self hasSuffix:@"\n"] || [self hasSuffix:@"\t"]) 35 | // [self replaceCharactersInRange:NSMakeRange(self.length-1, 1) withString:@""]; 36 | 37 | @autoreleasepool 38 | { 39 | NSUInteger stringLength = self.length; 40 | if (stringLength == 0) return self; 41 | 42 | NSUInteger indexBegin = 0; 43 | unichar invalidCharacters[] = {' ', '\n', '\t', '\0'}; 44 | int invalidCharactersSize = 4; 45 | 46 | unichar actualChar; 47 | int charIndex; 48 | BOOL invalid; 49 | while (indexBegin < stringLength) { 50 | invalid = false; 51 | actualChar = [self characterAtIndex:indexBegin]; 52 | for (charIndex = 0; charIndex < invalidCharactersSize; charIndex++) { 53 | if (invalidCharacters[charIndex] == actualChar) invalid = true; 54 | } 55 | if (invalid) indexBegin++; 56 | else break; 57 | } 58 | if (indexBegin > 0) { 59 | [self replaceCharactersInRange:NSMakeRange(0, indexBegin) withString:@""]; 60 | } 61 | if (indexBegin == stringLength) return self; 62 | 63 | 64 | stringLength = self.length; 65 | NSUInteger indexEnd = stringLength - 1; 66 | 67 | while (indexEnd >= 0) { 68 | invalid = false; 69 | actualChar = [self characterAtIndex:indexEnd]; 70 | for (charIndex = 0; charIndex < invalidCharactersSize; charIndex++) { 71 | if (invalidCharacters[charIndex] == actualChar) invalid = true; 72 | } 73 | if (invalid) indexEnd--; 74 | else break; 75 | } 76 | if (stringLength - indexEnd - 1 > 0) { 77 | [self replaceCharactersInRange:NSMakeRange(indexEnd + 1, stringLength - indexEnd - 1) withString:@""]; 78 | } 79 | } 80 | 81 | return self; 82 | } 83 | 84 | @end 85 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/NSMutableURLRequest+Extension.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSMutableURLRequest+Extension.h 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 22/02/17. 6 | // Copyright © 2017 Vitor Marques de Miranda. All rights reserved. 7 | // 8 | 9 | #ifndef NSMutableURLRequest_Extension_Class 10 | #define NSMutableURLRequest_Extension_Class 11 | 12 | #import 13 | 14 | @interface NSMutableURLRequest (VMMMutableURLRequest) 15 | 16 | -(void)ifModifiedSince:(nonnull NSDate*)modificationDate; 17 | 18 | @end 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/NSMutableURLRequest+Extension.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSMutableURLRequest+Extension.m 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 22/02/17. 6 | // Copyright © 2017 Vitor Marques de Miranda. All rights reserved. 7 | // 8 | 9 | #import "NSMutableURLRequest+Extension.h" 10 | 11 | static NSString* const RFC2822_STANDARD = @"EEE, dd MMM yyyy HH:mm:ss Z"; 12 | static NSString* const RFC2822_LOCALE = @"en_US_POSIX"; 13 | static NSString* const IF_MODIFIED_SINCE_HEADER = @"If-Modified-Since"; 14 | 15 | @implementation NSMutableURLRequest (VMMMutableURLRequest) 16 | 17 | -(void)ifModifiedSince:(nonnull NSDate*)modificationDate 18 | { 19 | NSString *dateString; 20 | 21 | @autoreleasepool 22 | { 23 | NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; 24 | dateFormatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:RFC2822_LOCALE]; 25 | dateFormatter.dateFormat = RFC2822_STANDARD; 26 | dateString = [dateFormatter stringFromDate:modificationDate]; 27 | } 28 | 29 | [self addValue:dateString forHTTPHeaderField:IF_MODIFIED_SINCE_HEADER]; 30 | } 31 | 32 | @end 33 | 34 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/NSRunningApplication+Extension.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSRunningApplication+Extension.h 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 23/09/17. 6 | // Copyright © 2017 Vitor Marques de Miranda. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSRunningApplication (VMMRunningApplication) 12 | 13 | -(nonnull NSArray*)visibleWindows; 14 | 15 | -(BOOL)isVisible; 16 | 17 | -(nonnull NSArray*)visibleWindowsSizes; 18 | -(nullable NSDictionary*)windowWithSize:(NSSize)size; 19 | -(BOOL)hasWindowWithSize:(NSSize)size; 20 | 21 | -(void)bringWindowsToFront; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/NSRunningApplication+Extension.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSRunningApplication+Extension.m 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 23/09/17. 6 | // Copyright © 2017 Vitor Marques de Miranda. All rights reserved. 7 | // 8 | // References: 9 | // https://stackoverflow.com/questions/6160727/how-to-obtain-info-of-the-program-from-the-window-list-with-cgwindowlistcopywind 10 | // https://superuser.com/questions/902869/how-to-identify-which-process-is-running-which-window-in-mac-os-x 11 | // 12 | 13 | #import "NSRunningApplication+Extension.h" 14 | 15 | @implementation NSRunningApplication (VMMRunningApplication) 16 | 17 | -(NSArray*)visibleWindows 18 | { 19 | NSMutableArray* appWindows = [[NSMutableArray alloc] init]; 20 | 21 | @autoreleasepool 22 | { 23 | NSMutableArray* windows = (NSMutableArray *)CFBridgingRelease(CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements, kCGNullWindowID)); 24 | 25 | for (NSDictionary *window in windows) 26 | { 27 | int ownerPid = [window[@"kCGWindowOwnerPID"] intValue]; 28 | if (ownerPid == self.processIdentifier) 29 | { 30 | [appWindows addObject:window]; 31 | } 32 | } 33 | } 34 | 35 | return appWindows; 36 | } 37 | 38 | -(BOOL)isVisible 39 | { 40 | return self.visibleWindows.count > 0; 41 | } 42 | 43 | -(nonnull NSArray*)visibleWindowsSizes 44 | { 45 | return [self.visibleWindows valueForKey:@"kCGWindowBounds"]; 46 | } 47 | -(nullable NSDictionary*)windowWithSize:(NSSize)size 48 | { 49 | for (NSDictionary *window in self.visibleWindows) 50 | { 51 | NSDictionary* windowBounds = window[@"kCGWindowBounds"]; 52 | CGFloat windowHeight = [windowBounds[@"Height"] doubleValue]; 53 | CGFloat windowWidth = [windowBounds[@"Width"] doubleValue]; 54 | if (ABS(size.width - windowWidth) < 0.1 && ABS(size.height - windowHeight) < 0.1) 55 | { 56 | return window; 57 | } 58 | } 59 | 60 | return nil; 61 | } 62 | -(BOOL)hasWindowWithSize:(NSSize)size 63 | { 64 | return [self windowWithSize:size] != nil; 65 | } 66 | 67 | -(void)bringWindowsToFront 68 | { 69 | [self activateWithOptions:(NSApplicationActivateAllWindows | NSApplicationActivateIgnoringOtherApps)]; 70 | } 71 | 72 | @end 73 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/NSSavePanel+Extension.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSSavePanel+Extension.h 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 22/02/17. 6 | // Copyright © 2017 Vitor Marques de Miranda. All rights reserved. 7 | // 8 | 9 | #ifndef NSSavePanel_Extension_Class 10 | #define NSSavePanel_Extension_Class 11 | 12 | #import 13 | 14 | @interface NSOpenPanel (VMMOpenPanel) 15 | 16 | +(void)runThreadSafeModalWithOpenPanel:(void (^)(NSOpenPanel* openPanel))optionsForPanel completionHandler:(void (^) (NSArray* selectedUrls))completionHandler; 17 | +(void)runMainThreadModalWithOpenPanel:(void (^)(NSOpenPanel* openPanel))optionsForPanel completionHandler:(void (^) (NSArray* selectedUrls))completionHandler; 18 | +(NSArray*)runBackgroundThreadModalWithOpenPanel:(void (^)(NSOpenPanel* openPanel))optionsForPanel; 19 | 20 | @end 21 | 22 | @interface NSSavePanel (VMMSavePanel) 23 | 24 | -(NSUInteger)runBackgroundThreadModalWithWindow; 25 | 26 | +(void)runThreadSafeModalWithSavePanel:(void (^)(NSSavePanel* savePanel))optionsForPanel completionHandler:(void (^) (NSURL* selectedUrl))completionHandler; 27 | +(void)runMainThreadModalWithSavePanel:(void (^)(NSSavePanel* savePanel))optionsForPanel completionHandler:(void (^) (NSURL* selectedUrl))completionHandler; 28 | +(NSURL*)runBackgroundThreadModalWithSavePanel:(void (^)(NSSavePanel* savePanel))optionsForPanel; 29 | 30 | -(void)setInitialDirectory:(NSString*)path; 31 | 32 | -(void)setWindowTitle:(NSString*)string; 33 | 34 | @end 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/NSSavePanel+Extension.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSSavePanel+Extension.m 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 22/02/17. 6 | // Copyright © 2017 Vitor Marques de Miranda. All rights reserved. 7 | // 8 | 9 | #import "NSSavePanel+Extension.h" 10 | 11 | #import "NSThread+Extension.h" 12 | 13 | #import "VMMComputerInformation.h" 14 | 15 | #import "VMMModals.h" 16 | 17 | @implementation NSOpenPanel (VMMOpenPanel) 18 | 19 | +(void)runThreadSafeModalWithOpenPanel:(void (^)(NSOpenPanel* openPanel))optionsForPanel completionHandler:(void (^) (NSArray* selectedUrls))completionHandler 20 | { 21 | if ([NSThread isMainThread]) 22 | { 23 | [self runMainThreadModalWithOpenPanel:optionsForPanel completionHandler:completionHandler]; 24 | } 25 | else 26 | { 27 | NSArray* selectedUrls = [self runBackgroundThreadModalWithOpenPanel:optionsForPanel]; 28 | completionHandler(selectedUrls); 29 | } 30 | } 31 | +(void)runMainThreadModalWithOpenPanel:(void (^)(NSOpenPanel* openPanel))optionsForPanel completionHandler:(void (^) (NSArray* selectedUrls))completionHandler 32 | { 33 | NSOpenPanel* openPanel = [NSOpenPanel openPanel]; 34 | optionsForPanel(openPanel); 35 | 36 | NSWindow* window = [VMMModals modalsWindow]; 37 | if (window != nil) 38 | { 39 | [openPanel beginSheetModalForWindow:window completionHandler:^(NSModalResponse result) 40 | { 41 | [openPanel orderOut:nil]; 42 | 43 | if (result == NSOKButton) 44 | { 45 | completionHandler([openPanel URLs]); 46 | } 47 | }]; 48 | } 49 | else 50 | { 51 | if ([openPanel runModal] == NSOKButton) 52 | { 53 | completionHandler([openPanel URLs]); 54 | } 55 | } 56 | } 57 | +(NSArray*)runBackgroundThreadModalWithOpenPanel:(void (^)(NSOpenPanel* openPanel))optionsForPanel 58 | { 59 | __block NSArray* urlsList; 60 | 61 | NSCondition* lock = [[NSCondition alloc] init]; 62 | __block NSUInteger value; 63 | 64 | [NSThread dispatchBlockInMainQueue:^ 65 | { 66 | NSOpenPanel* openPanel = [NSOpenPanel openPanel]; 67 | optionsForPanel(openPanel); 68 | 69 | [NSThread dispatchQueueWithName:"open-panel-background-thread" priority:DISPATCH_QUEUE_PRIORITY_DEFAULT concurrent:NO withBlock:^ 70 | { 71 | value = [openPanel runBackgroundThreadModalWithWindow]; 72 | if (value == NSOKButton) 73 | { 74 | urlsList = [openPanel URLs]; 75 | } 76 | 77 | [lock signal]; 78 | }]; 79 | }]; 80 | 81 | [lock lock]; 82 | [lock wait]; 83 | [lock unlock]; 84 | 85 | return urlsList; 86 | } 87 | 88 | @end 89 | 90 | @implementation NSSavePanel (VMMSavePanel) 91 | 92 | -(NSUInteger)runBackgroundThreadModalWithWindow 93 | { 94 | NSWindow* window = [VMMModals modalsWindow]; 95 | 96 | __block NSUInteger value; 97 | NSCondition* lock = [[NSCondition alloc] init]; 98 | 99 | [NSThread dispatchBlockInMainQueue:^ 100 | { 101 | if (window != nil) 102 | { 103 | [self beginSheetModalForWindow:window completionHandler:^(NSModalResponse result) 104 | { 105 | [self orderOut:nil]; 106 | value = result; 107 | [lock signal]; 108 | }]; 109 | } 110 | else 111 | { 112 | value = [self runModal]; 113 | [lock signal]; 114 | } 115 | }]; 116 | 117 | [lock lock]; 118 | [lock wait]; 119 | [lock unlock]; 120 | 121 | return value; 122 | } 123 | 124 | +(void)runThreadSafeModalWithSavePanel:(void (^)(NSSavePanel* savePanel))optionsForPanel completionHandler:(void (^) (NSURL* selectedUrl))completionHandler 125 | { 126 | if ([NSThread isMainThread]) 127 | { 128 | [self runMainThreadModalWithSavePanel:optionsForPanel completionHandler:completionHandler]; 129 | } 130 | else 131 | { 132 | NSURL* selectedUrl = [self runBackgroundThreadModalWithSavePanel:optionsForPanel]; 133 | completionHandler(selectedUrl); 134 | } 135 | } 136 | +(void)runMainThreadModalWithSavePanel:(void (^)(NSSavePanel* savePanel))optionsForPanel completionHandler:(void (^) (NSURL* selectedUrl))completionHandler 137 | { 138 | NSSavePanel* savePanel = [NSSavePanel savePanel]; 139 | optionsForPanel(savePanel); 140 | 141 | NSWindow* window = [VMMModals modalsWindow]; 142 | if (window != nil) 143 | { 144 | [savePanel beginSheetModalForWindow:window completionHandler:^(NSModalResponse result) 145 | { 146 | [savePanel orderOut:nil]; 147 | 148 | if (result == NSOKButton) 149 | { 150 | completionHandler([savePanel URL]); 151 | } 152 | }]; 153 | } 154 | else 155 | { 156 | if ([savePanel runModal] == NSOKButton) 157 | { 158 | completionHandler([savePanel URL]); 159 | } 160 | } 161 | } 162 | +(NSURL*)runBackgroundThreadModalWithSavePanel:(void (^)(NSSavePanel* savePanel))optionsForPanel 163 | { 164 | __block NSURL* url; 165 | 166 | NSCondition* lock = [[NSCondition alloc] init]; 167 | __block NSUInteger value; 168 | 169 | [NSThread dispatchBlockInMainQueue:^ 170 | { 171 | NSSavePanel* savePanel = [NSSavePanel savePanel]; 172 | optionsForPanel(savePanel); 173 | 174 | [NSThread dispatchQueueWithName:"save-panel-background-thread" priority:DISPATCH_QUEUE_PRIORITY_DEFAULT concurrent:NO withBlock:^ 175 | { 176 | value = [savePanel runBackgroundThreadModalWithWindow]; 177 | if (value == NSOKButton) 178 | { 179 | url = [savePanel URL]; 180 | } 181 | 182 | [lock signal]; 183 | }]; 184 | }]; 185 | 186 | [lock lock]; 187 | [lock wait]; 188 | [lock unlock]; 189 | 190 | return url; 191 | } 192 | 193 | -(void)setInitialDirectory:(NSString*)path 194 | { 195 | [self setDirectoryURL:[NSURL fileURLWithPath:path isDirectory:YES]]; 196 | } 197 | 198 | -(void)setWindowTitle:(NSString*)string 199 | { 200 | if ([self isKindOfClass:[NSOpenPanel class]]) 201 | { 202 | if (IS_SYSTEM_MAC_OS_10_11_OR_SUPERIOR) 203 | { 204 | [self setMessage:string]; 205 | } 206 | else 207 | { 208 | [self setTitle:string]; 209 | } 210 | } 211 | else 212 | { 213 | [self setTitle:string]; 214 | } 215 | } 216 | 217 | @end 218 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/NSScreen+Extension.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSScreen+Extension.h 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 04/10/2017. 6 | // Copyright © 2017 VitorMM. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSScreen (VMMScreen) 12 | 13 | -(CGFloat)retinaScale; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/NSScreen+Extension.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSScreen+Extension.m 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 04/10/2017. 6 | // Copyright © 2017 VitorMM. All rights reserved. 7 | // 8 | 9 | #import "NSScreen+Extension.h" 10 | 11 | @implementation NSScreen (VMMScreen) 12 | 13 | -(CGFloat)retinaScale 14 | { 15 | return [self respondsToSelector:@selector(backingScaleFactor)] ? self.backingScaleFactor : self.userSpaceScaleFactor; 16 | } 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/NSString+Extension.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+Extension.h 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 22/02/17. 6 | // Copyright © 2017 Vitor Marques de Miranda. All rights reserved. 7 | // 8 | 9 | #ifndef NSString_Extension_Class 10 | #define NSString_Extension_Class 11 | 12 | #import 13 | 14 | @interface NSString (VMMString) 15 | 16 | +(nonnull NSString*)stringWithCFTypeIDDescription:(CFTypeRef _Nonnull)cf_type; 17 | +(nullable NSString*)stringWithCFString:(CFStringRef _Nonnull)cf_string; 18 | +(nonnull NSString*)stringWithCFNumber:(CFNumberRef _Nonnull)cf_number ofType:(CFNumberType)number_type; 19 | +(nullable NSString*)stringWithCFType:(CFTypeRef _Nonnull)cf_type; 20 | 21 | -(NSRange)rangeOfUnescapedChar:(char)character; 22 | -(NSRange)rangeOfUnescapedChar:(char)character range:(NSRange)rangeOfReceiverToSearch; 23 | 24 | -(BOOL)contains:(nonnull NSString*)string; 25 | -(BOOL)matchesWithSearchTerms:(nonnull NSArray*)searchTerms; 26 | -(nonnull NSArray*)searchTermsWithString; 27 | 28 | -(BOOL)matchesWithRegex:(nonnull NSString*)regexString; 29 | -(nonnull NSArray*)componentsMatchingWithRegex:(nonnull NSString*)regexString; 30 | 31 | +(nonnull NSString*)humanReadableSizeForBytes:(long long int)bytes withDecimalMeasureSystem:(BOOL)measure; 32 | 33 | -(nonnull NSString*)hexadecimalUTF8String; 34 | +(nullable NSString*)stringWithHexadecimalUTF8String:(nonnull NSString*)string; 35 | 36 | +(nonnull NSString*)stringByRemovingEvenCharsFromString:(nonnull NSString*)text; 37 | -(nonnull NSString*)stringToWebStructure; 38 | 39 | -(NSRange)rangeAfterString:(nullable NSString*)before andBeforeString:(nullable NSString*)after; 40 | -(nullable NSString*)getFragmentAfter:(nullable NSString*)before andBefore:(nullable NSString*)after; 41 | 42 | -(nullable NSNumber*)initialIntegerValue; 43 | 44 | +(nullable NSString*)stringWithContentsOfFile:(nonnull NSString*)file; 45 | +(nullable NSString*)stringWithContentsOfFile:(nonnull NSString*)file encoding:(NSStringEncoding)enc; 46 | +(void)stringWithContentsOfURL:(nonnull NSURL *)url encoding:(NSStringEncoding)enc timeoutInterval:(long long int)timeoutInterval withCompletionHandler:(void (^_Nullable)(NSUInteger statusCode, NSString* _Nullable string, NSError* _Nullable error))completion; 47 | 48 | -(BOOL)writeToFile:(nonnull NSString*)path atomically:(BOOL)useAuxiliaryFile encoding:(NSStringEncoding)enc; 49 | 50 | -(nonnull NSData*)dataWithBase64Encoding; 51 | 52 | -(BOOL)isAValidURL; 53 | 54 | -(NSString*)stringByReplacingCharactersInSet:(NSCharacterSet *)characterset withString:(NSString *)string; 55 | -(NSString*)stringByRemovingCharactersInSet:(NSCharacterSet *)characterset; 56 | 57 | @end 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/NSTask+Extension.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSTask+Extension.h 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 22/02/17. 6 | // Copyright © 2017 Vitor Marques de Miranda. All rights reserved. 7 | // 8 | 9 | #ifndef NSTask_Extension_Class 10 | #define NSTask_Extension_Class 11 | 12 | #import 13 | 14 | @interface NSTask (VMMTask) 15 | 16 | +(NSArray*)componentsFromFlagsString:(NSString*)initialFlags; 17 | 18 | +(NSString*)runCommand:(NSArray*)programAndFlags; 19 | +(NSString*)runCommand:(NSArray*)programAndFlags atRunPath:(NSString*)path; 20 | +(NSString*)runCommand:(NSArray*)programAndFlags atRunPath:(NSString*)path andWait:(BOOL)shouldWait; 21 | 22 | +(void)runAsynchronousCommand:(NSArray*)programAndFlags; 23 | 24 | +(NSString*)runProgram:(NSString*)program; 25 | +(NSString*)runProgram:(NSString*)program withFlags:(NSArray*)flags; 26 | +(NSString*)runProgram:(NSString*)program withFlags:(NSArray*)flags outputEncoding:(NSStringEncoding)encoding; 27 | +(NSString*)runProgram:(NSString*)program withFlags:(NSArray*)flags atRunPath:(NSString*)path andWaiting:(BOOL)wait; 28 | +(NSString*)runProgram:(NSString*)program withFlags:(NSArray*)flags withEnvironment:(NSDictionary*)env; 29 | +(NSString*)runProgram:(NSString*)program withFlags:(NSArray*)flags atRunPath:(NSString*)path withEnvironment:(NSDictionary*)env; 30 | +(NSString*)runProgram:(NSString*)program withFlags:(NSArray*)flags waitingForTimeInterval:(unsigned int)timeout; 31 | 32 | +(void)runAsynchronousProgram:(NSString*)program withFlags:(NSArray*)flags withEnvironment:(NSDictionary*)env; 33 | +(void)runAsynchronousProgram:(NSString*)program withFlags:(NSArray*)flags atRunPath:(NSString*)path withEnvironment:(NSDictionary*)env; 34 | 35 | +(NSString*)runProgram:(NSString*)program withFlags:(NSArray*)flags atRunPath:(NSString*)path withEnvironment:(NSDictionary*)env andWaiting:(BOOL)wait forTimeInterval:(unsigned int)timeout outputEncoding:(NSStringEncoding)encoding; 36 | 37 | @end 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/NSText+Extension.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSText+Extension.h 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 22/02/17. 6 | // Copyright © 2017 Vitor Marques de Miranda. All rights reserved. 7 | // 8 | 9 | #ifndef NSText_Extension_Class 10 | #define NSText_Extension_Class 11 | 12 | #import 13 | 14 | @interface NSText (VMMText) 15 | -(void)setSelectedRangeAsTheBeginOfTheField; 16 | -(void)setSelectedRangeAsTheEndOfTheField; 17 | @end 18 | 19 | @interface NSTextView (VMMTextView) 20 | -(void)setJustifiedAttributedString:(NSAttributedString*)string withColor:(NSColor*)color; 21 | -(void)deselectText; 22 | -(void)scrollToBottom; 23 | @end 24 | 25 | @interface NSTextField (VMMTextField) 26 | -(void)setSelectedRangeAsTheBeginOfTheField; 27 | -(void)setSelectedRangeAsTheEndOfTheField; 28 | -(void)setAnyStringValue:(NSString*)stringValue; 29 | @end 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/NSText+Extension.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSText+Extension.m 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 22/02/17. 6 | // Copyright © 2017 Vitor Marques de Miranda. All rights reserved. 7 | // 8 | 9 | #import "NSText+Extension.h" 10 | 11 | #import "NSMutableAttributedString+Extension.h" 12 | 13 | #import "VMMComputerInformation.h" 14 | 15 | @implementation NSText (VMMText) 16 | -(void)setSelectedRangeAsTheBeginOfTheField 17 | { 18 | [self setSelectedRange:NSMakeRange(0,0)]; 19 | } 20 | -(void)setSelectedRangeAsTheEndOfTheField 21 | { 22 | [self setSelectedRange:NSMakeRange(self.string.length,0)]; 23 | } 24 | @end 25 | 26 | @implementation NSTextView (VMMTextView) 27 | -(void)setJustifiedAttributedString:(NSAttributedString*)string withColor:(NSColor*)color 28 | { 29 | NSMutableAttributedString* str = string ? [string mutableCopy] : [[NSMutableAttributedString alloc] init]; 30 | 31 | [self scrollRangeToVisible:NSMakeRange(0,0)]; 32 | [self setSelectedRange:NSMakeRange(0, 0)]; 33 | 34 | if (color != nil) [str setFontColor:color]; 35 | 36 | // NSTextAlignment values changed in macOS 10.11 37 | // https://developer.apple.com/library/content/releasenotes/AppKit/RN-AppKitOlderNotes/index.html#10_11DynamicTracking 38 | 39 | [str setTextJustified]; 40 | 41 | [[self textStorage] setAttributedString:str]; 42 | } 43 | -(void)deselectText 44 | { 45 | [self setSelectable:NO]; 46 | [self setSelectable:YES]; 47 | } 48 | -(void)scrollToBottom 49 | { 50 | // Reference: 51 | // https://stackoverflow.com/a/28708474/4370893 52 | 53 | NSPoint pt = NSMakePoint(0, 100000000000.0); 54 | 55 | id scrollView = [self enclosingScrollView]; 56 | id clipView = [scrollView contentView]; 57 | 58 | pt = [clipView constrainScrollPoint:pt]; 59 | [clipView scrollToPoint:pt]; 60 | [scrollView reflectScrolledClipView:clipView]; 61 | } 62 | @end 63 | 64 | @implementation NSTextField (VMMTextField) 65 | -(void)setSelectedRangeAsTheBeginOfTheField 66 | { 67 | [[self currentEditor] setSelectedRangeAsTheBeginOfTheField]; 68 | } 69 | -(void)setSelectedRangeAsTheEndOfTheField 70 | { 71 | [[self currentEditor] setSelectedRangeAsTheEndOfTheField]; 72 | } 73 | -(void)setAnyStringValue:(NSString*)stringValue 74 | { 75 | [self setStringValue:stringValue ? stringValue : @""]; 76 | } 77 | @end 78 | 79 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/NSThread+Extension.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSThread+Extension.h 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 22/02/17. 6 | // Copyright © 2017 Vitor Marques de Miranda. All rights reserved. 7 | // 8 | 9 | #ifndef NSThread_Extension_Class 10 | #define NSThread_Extension_Class 11 | 12 | #import 13 | 14 | #define threadSafeUiValue(__value) [NSThread returnThreadSafeBlock:^id{ return (__value); }] 15 | 16 | dispatch_queue_t queueWithNameAndPriority(const char* name, long priority, BOOL concurrent); 17 | 18 | @interface NSThread (VMMThread) 19 | 20 | +(void)dispatchQueueWithName:(const char*)name priority:(long)priority concurrent:(BOOL)concurrent withBlock:(void (^)(void))thread; 21 | +(void)dispatchBlockInMainQueue:(void (^)(void))thread; 22 | 23 | +(void)runThreadSafeBlock:(void (^)(void))block; 24 | 25 | +(id)returnThreadSafeBlock:(id (^)(void))block; 26 | 27 | @end 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/NSThread+Extension.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSThread+Extension.m 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 22/02/17. 6 | // Copyright © 2017 Vitor Marques de Miranda. All rights reserved. 7 | // 8 | 9 | #import "NSThread+Extension.h" 10 | 11 | dispatch_queue_t queueWithNameAndPriority(const char* name, long priority, BOOL concurrent) 12 | { 13 | dispatch_queue_t dispatchQueue = dispatch_queue_create(name, concurrent ? DISPATCH_QUEUE_CONCURRENT : DISPATCH_QUEUE_SERIAL); 14 | dispatch_queue_t priorityQueue = dispatch_get_global_queue(priority, 0); 15 | dispatch_set_target_queue(dispatchQueue, priorityQueue); 16 | return dispatchQueue; 17 | } 18 | 19 | @implementation NSThread (VMMThread) 20 | 21 | +(void)dispatchQueueWithName:(const char*)name priority:(long)priority concurrent:(BOOL)concurrent withBlock:(void (^)(void))thread 22 | { 23 | dispatch_async(queueWithNameAndPriority(name, priority, concurrent), ^ 24 | { 25 | thread(); 26 | }); 27 | } 28 | +(void)dispatchBlockInMainQueue:(void (^)(void))thread 29 | { 30 | dispatch_async(dispatch_get_main_queue(), ^ 31 | { 32 | thread(); 33 | }); 34 | } 35 | 36 | +(void)runThreadSafeBlock:(void (^)(void))block 37 | { 38 | if ([NSThread isMainThread]) 39 | { 40 | block(); 41 | } 42 | else 43 | { 44 | NSCondition* lock = [[NSCondition alloc] init]; 45 | 46 | [NSThread dispatchBlockInMainQueue:^ 47 | { 48 | block(); 49 | 50 | [lock signal]; 51 | }]; 52 | 53 | [lock lock]; 54 | [lock wait]; 55 | [lock unlock]; 56 | } 57 | } 58 | 59 | +(id)returnThreadSafeBlock:(id (^)(void))block 60 | { 61 | if ([NSThread isMainThread]) 62 | { 63 | return block(); 64 | } 65 | else 66 | { 67 | __block id object; 68 | NSCondition* lock = [[NSCondition alloc] init]; 69 | 70 | [NSThread dispatchBlockInMainQueue:^ 71 | { 72 | object = block(); 73 | 74 | [lock signal]; 75 | }]; 76 | 77 | [lock lock]; 78 | [lock wait]; 79 | [lock unlock]; 80 | 81 | return object; 82 | } 83 | } 84 | 85 | @end 86 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/NSTimer+Extension.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSTimer+Extension.h 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 23/11/2017. 6 | // Copyright © 2017 VitorMM. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface VMMTimerListener : NSObject 12 | 13 | @property (nonatomic, strong) NSTimer* _Nullable timer; 14 | @property (nonatomic, strong) void (^block)(NSTimer* timer); 15 | 16 | @end 17 | 18 | @interface NSTimer (VMMTimer) 19 | 20 | +(nonnull NSTimer*)scheduledTimerWithRunLoopMode:(nonnull NSRunLoopMode)runLoopMode timeInterval:(NSTimeInterval)interval target:(nonnull id)target selector:(nonnull SEL)selector userInfo:(nullable id)userInfo; 21 | 22 | +(nonnull VMMTimerListener*)scheduledTimerWithRunLoopMode:(nonnull NSRunLoopMode)runLoopMode timeInterval:(NSTimeInterval)interval repeats:(BOOL)repeats block:(void (^)(NSTimer* _Nonnull timer))block; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/NSTimer+Extension.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSTimer+Extension.m 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 23/11/2017. 6 | // Copyright © 2017 VitorMM. All rights reserved. 7 | // 8 | 9 | #import "NSTimer+Extension.h" 10 | #import "VMMComputerInformation.h" 11 | 12 | @implementation VMMTimerListener 13 | 14 | -(void)listen { 15 | _block(_timer); 16 | } 17 | 18 | @end 19 | 20 | @implementation NSTimer (VMMTimer) 21 | 22 | +(nonnull NSTimer*)scheduledTimerWithRunLoopMode:(nonnull NSRunLoopMode)runLoopMode timeInterval:(NSTimeInterval)interval target:(nonnull id)target selector:(nonnull SEL)selector userInfo:(nullable id)userInfo 23 | { 24 | NSTimer* timer = [NSTimer scheduledTimerWithTimeInterval:interval target:target selector:selector userInfo:userInfo repeats:YES]; 25 | NSRunLoop* theRunLoop = [NSRunLoop currentRunLoop]; 26 | [theRunLoop addTimer:timer forMode:runLoopMode]; 27 | return timer; 28 | } 29 | 30 | +(nonnull VMMTimerListener*)scheduledTimerWithRunLoopMode:(nonnull NSRunLoopMode)runLoopMode timeInterval:(NSTimeInterval)interval repeats:(BOOL)repeats block:(void (^)(NSTimer* _Nonnull timer))block 31 | { 32 | VMMTimerListener* listener = [[VMMTimerListener alloc] init]; 33 | listener.block = block; 34 | listener.timer = [NSTimer timerWithTimeInterval:interval target:listener selector:@selector(listen) userInfo:nil repeats:repeats]; 35 | 36 | NSRunLoop* theRunLoop = [NSRunLoop currentRunLoop]; 37 | [theRunLoop addTimer:listener.timer forMode:runLoopMode]; 38 | return listener; 39 | } 40 | 41 | @end 42 | 43 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/NSUnarchiver+Extension.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSUnarchiver+Extension.h 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 22/02/17. 6 | // Copyright © 2017 Vitor Marques de Miranda. All rights reserved. 7 | // 8 | 9 | #ifndef NSUnarchiver_Extension_Class 10 | #define NSUnarchiver_Extension_Class 11 | 12 | #import 13 | 14 | @interface NSUnarchiver (VMMUnarchiver) 15 | 16 | +(nullable id)safeUnarchiveObjectWithData:(nonnull NSData*)data; 17 | +(nullable id)safeUnarchiveObjectFromFile:(nonnull NSString*)path; 18 | 19 | @end 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/NSUnarchiver+Extension.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSUnarchiver+Extension.m 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 22/02/17. 6 | // Copyright © 2017 Vitor Marques de Miranda. All rights reserved. 7 | // 8 | 9 | #import "NSUnarchiver+Extension.h" 10 | 11 | #import "NSData+Extension.h" 12 | 13 | @implementation NSUnarchiver (VMMUnarchiver) 14 | 15 | +(nullable id)safeUnarchiveObjectWithData:(nonnull NSData*)data 16 | { 17 | @try 18 | { 19 | return [self unarchiveObjectWithData:data]; 20 | } 21 | @catch (NSException *exception) 22 | { 23 | return nil; 24 | } 25 | } 26 | +(nullable id)safeUnarchiveObjectFromFile:(nonnull NSString*)path 27 | { 28 | if (![[NSFileManager defaultManager] fileExistsAtPath:path]) return nil; 29 | 30 | id contents = nil; 31 | 32 | @autoreleasepool 33 | { 34 | NSData* data = [NSData safeDataWithContentsOfFile:path]; 35 | if (!data || data.length == 0) return nil; 36 | 37 | contents = [self safeUnarchiveObjectWithData:data]; 38 | } 39 | 40 | return contents; 41 | } 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/NSUserDefaults+Extension.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSUserDefaults+Extension.h 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 31/08/17. 6 | // Copyright © 2017 Vitor Marques de Miranda. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSUserDefaults (VMMUserDefaults) 12 | 13 | -(nonnull id)objectForKey:(nonnull NSString *)key withDefaultValue:(nonnull id)value; 14 | 15 | -(BOOL)preferExternalGPU; 16 | -(void)setPreferExternalGPU:(BOOL)prefer; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/NSUserDefaults+Extension.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSUserDefaults+Extension.m 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 31/08/17. 6 | // Copyright © 2017 Vitor Marques de Miranda. All rights reserved. 7 | // 8 | 9 | #import "NSUserDefaults+Extension.h" 10 | 11 | #import "VMMComputerInformation.h" 12 | #import "VMMLogUtility.h" 13 | 14 | @implementation NSUserDefaults (VMMUserDefaults) 15 | 16 | -(nonnull id)objectForKey:(nonnull NSString *)key withDefaultValue:(nonnull id)value 17 | { 18 | id actualValue = [self objectForKey:key]; 19 | 20 | if (actualValue == nil) 21 | { 22 | [self setObject:value forKey:key]; 23 | return value; 24 | } 25 | 26 | return actualValue; 27 | } 28 | 29 | -(BOOL)preferExternalGPU 30 | { 31 | // Reference: 32 | // https://egpu.io/forums/mac-setup/potentially-accelerate-all-applications-on-egpu-macos-10-13-4/ 33 | 34 | if ([VMMComputerInformation macOsCompatibilityWithExternalGPU] != VMMExternalGPUCompatibilityWithMacOS_Supported) { 35 | NSDebugLog(@"\"Prefer External GPU\" was not available prior to macOS 10.13.4. Using that probably wont't change anything."); 36 | } 37 | 38 | NSString* appReturn = [self objectForKey:@"GPUSelectionPolicy"]; 39 | return appReturn != nil && [appReturn isKindOfClass:[NSString class]] && [appReturn isEqualToString:@"preferRemovable"]; 40 | } 41 | -(void)setPreferExternalGPU:(BOOL)prefer 42 | { 43 | if ([VMMComputerInformation macOsCompatibilityWithExternalGPU] != VMMExternalGPUCompatibilityWithMacOS_Supported) { 44 | NSDebugLog(@"\"Prefer External GPU\" was not available prior to macOS 10.13.4. Using that probably wont't change anything."); 45 | } 46 | 47 | if (prefer) { 48 | [self setObject:@"preferRemovable" forKey:@"GPUSelectionPolicy"]; 49 | } 50 | else { 51 | [self removeObjectForKey:@"GPUSelectionPolicy"]; 52 | } 53 | } 54 | 55 | @end 56 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/NSView+Extension.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSView+Extension.h 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 04/09/17. 6 | // Copyright © 2017 Vitor Marques de Miranda. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSView (VMMView_Extensions) 12 | 13 | -(void)removeAllSubviews; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/NSView+Extension.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSView+Extension.m 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 04/09/17. 6 | // Copyright © 2017 Vitor Marques de Miranda. All rights reserved. 7 | // 8 | 9 | #import "NSView+Extension.h" 10 | 11 | @implementation NSView (VMMView_Extensions) 12 | 13 | -(void)removeAllSubviews 14 | { 15 | NSArray* subviewsArray = [self subviews]; 16 | for (int i = (int)subviewsArray.count - 1; i >= 0 ; i--) 17 | { 18 | [subviewsArray[i] removeFromSuperview]; 19 | } 20 | } 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/NSWorkspace+Extension.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSWorkspace+Extension.h 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 24/11/2017. 6 | // Copyright © 2017 VitorMM. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSWorkspace (VMMWorkspace) 12 | 13 | -(nonnull NSArray*)runningApplicationsFromInsideBundle:(nonnull NSString*)bundlePath; 14 | 15 | -(void)forceOpenURL:(nonnull NSURL*)url; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/NSWorkspace+Extension.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSWorkspace+Extension.m 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 24/11/2017. 6 | // Copyright © 2017 VitorMM. All rights reserved. 7 | // 8 | 9 | #import "NSWorkspace+Extension.h" 10 | 11 | #import "NSTask+Extension.h" 12 | 13 | @implementation NSWorkspace (VMMWorkspace) 14 | 15 | -(nonnull NSArray*)runningApplicationsFromInsideBundle:(nonnull NSString*)bundlePath 16 | { 17 | NSMutableArray* list = [[NSMutableArray alloc] init]; 18 | 19 | @autoreleasepool 20 | { 21 | for (NSRunningApplication* runningApp in [self runningApplications]) 22 | { 23 | NSString* binLocalPath = [[runningApp executableURL] path]; 24 | 25 | if (binLocalPath != nil) 26 | { 27 | if (![binLocalPath hasPrefix:bundlePath] && [bundlePath hasPrefix:@"/private"]) 28 | { 29 | binLocalPath = [@"/private" stringByAppendingString:binLocalPath]; 30 | } 31 | 32 | if ([binLocalPath hasPrefix:bundlePath]) 33 | { 34 | [list addObject:runningApp]; 35 | } 36 | } 37 | } 38 | } 39 | 40 | return list; 41 | } 42 | 43 | -(void)forceOpenURL:(nonnull NSURL*)url 44 | { 45 | BOOL opened = [self openURL:url]; 46 | 47 | if (opened == false) 48 | { 49 | [NSTask runProgram:@"open" withFlags:@[url.absoluteString]]; 50 | } 51 | } 52 | 53 | @end 54 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/ObjCExtensionConfig.h: -------------------------------------------------------------------------------- 1 | // 2 | // ObjCExtensionConfig.h 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 22/08/18. 6 | // Copyright © 2018 VitorMM. All rights reserved. 7 | // 8 | 9 | #ifndef ObjCExtensionConfig_h 10 | #define ObjCExtensionConfig_h 11 | 12 | 13 | #define I_WANT_TO_BE_RELEASED_IN_APPLE_STORE false 14 | // 15 | // Pretty straightforward. If you set this to TRUE, any of the conditions 16 | // below that may cause a rejection in the Apple Store will be automatically 17 | // disabled in the end of this file. 18 | // 19 | 20 | 21 | 22 | #define NSDEBUGLOG_SHOULD_PRINT_TO_A_DESKTOP_FILE_TOO false 23 | // 24 | // By enabling this, NSDebugLog should not only run as NSLog white in Debug, 25 | // but it should also create a debug.log file in your Desktop with the same 26 | // content. It's really useful in case you restart your app and lose some log, 27 | // and with Mojave's extra logs in the console, that gives you a source without 28 | // those extra contents. 29 | // 30 | 31 | 32 | 33 | #define USER_NOTIFICATIONS_SHOULD_SHOW_A_BIGGER_ICON true 34 | // 35 | // User notifications have two different icons. A big one with the app icon 36 | // in the left, and a squared smaller one in the right with a thumbnail. 37 | // 38 | // If this is set to FALSE and you ask VMMUserNotificationCenter to show a 39 | // notification with an icon, it's going to show the icon in the right side 40 | // of the notification. 41 | // 42 | // If this is set to TRUE and you ask VMMUserNotificationCenter to show a 43 | // notification with an icon, it's going to show the icon in the left side 44 | // of the notification, and the app icon will appear with a smaller side 45 | // next to the notification title, in the left. 46 | // 47 | // WARNING: Setting this to TRUE will make your app be rejected 48 | // in the Apple Store. 49 | // 50 | 51 | 52 | 53 | #define USE_THE_OPENGL_FRAMEWORK_WHEN_AVAILABLE true 54 | // 55 | // If you set this to TRUE, VMMComputerInformation will use the OpenGL framework to look 56 | // for video card information only if the OpenGL framework is available. 57 | // 58 | // If you set this to FALSE, you will need to import the OpenGL framework (and enable the 59 | // define below) to use the videoCardMemorySizesInMegabytesFromOpenGLAPI function of VMMVideoCard. 60 | // 61 | // WARNING: Setting this to TRUE will make your app be rejected 62 | // in the Apple Store. 63 | // 64 | 65 | 66 | 67 | #define IM_IMPORTING_THE_OPENGL_FRAMEWORK false 68 | // 69 | // If you import the OpenGL Framework, your app will be macOS 10.14- compatible only. 70 | // https://developer.apple.com/library/archive/documentation/GraphicsImaging/Conceptual/OpenGL-MacProgGuide/opengl_intro/opengl_intro.html 71 | // 72 | // If you want to use the VMMVideoCard videoCardMemorySizesInMegabytesFromOpenGLAPI function and still be 73 | // released in the Apple Store, set this to TRUE and add the OpenGL Framework to this project. 74 | // Otherwise, you can safely set this function to FALSE. If this and USE_THE_OPENGL_FRAMEWORK_WHEN_AVAILABLE 75 | // are set to FALSE, the videoCardMemorySizesInMegabytesFromOpenGLAPI function won't be available. 76 | // 77 | 78 | 79 | 80 | // DO NOT CHANGE WHAT'S BELOW THIS POINT! 81 | // THIS IS WHAT MAKES THE I_WANT_TO_BE_RELEASED_IN_APPLE_STORE 82 | // CONDITION WORK! 83 | 84 | #if I_WANT_TO_BE_RELEASED_IN_APPLE_STORE == true 85 | #define USER_NOTIFICATIONS_SHOULD_SHOW_A_BIGGER_ICON false 86 | #define USE_THE_OPENGL_FRAMEWORK_WHEN_AVAILABLE false 87 | #endif 88 | 89 | 90 | 91 | #define KEEP_DEVICE_CLASSES true 92 | 93 | 94 | #endif /* ObjCExtensionConfig_h */ 95 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/ObjectiveC_Extension.h: -------------------------------------------------------------------------------- 1 | // 2 | // ObjectiveC_Extension.h 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 29/09/17. 6 | // Copyright © 2017 VitorMM. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for ObjectiveC_Extension. 12 | FOUNDATION_EXPORT double ObjectiveC_ExtensionVersionNumber; 13 | 14 | //! Project version string for ObjectiveC_Extension. 15 | FOUNDATION_EXPORT const unsigned char ObjectiveC_ExtensionVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | #import 20 | 21 | // Devices 22 | #if KEEP_DEVICE_CLASSES == true 23 | #import 24 | #import 25 | #import 26 | #import 27 | #endif 28 | 29 | // Extensions 30 | #import 31 | #import 32 | #import 33 | #import 34 | #import 35 | #import 36 | #import 37 | #import 38 | #import 39 | #import 40 | #import 41 | #import 42 | #import 43 | #import 44 | #import 45 | #import 46 | #import 47 | #import 48 | #import 49 | #import 50 | #import 51 | #import 52 | #import 53 | #import 54 | #import 55 | #import 56 | #import 57 | #import 58 | 59 | // Utilities 60 | #import 61 | #import 62 | #import 63 | #import 64 | #import 65 | #import 66 | #import 67 | #import 68 | #import 69 | #import 70 | #import 71 | #import 72 | #import 73 | 74 | // Views 75 | #import 76 | #import 77 | #import 78 | #import 79 | #import 80 | #import 81 | 82 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/SZJsonParser.h: -------------------------------------------------------------------------------- 1 | // 2 | // SZJsonParser.h 3 | // JSON Parser 4 | // 5 | // Created by numata on 09/09/04. 6 | // Copyright 2009 Satoshi Numata. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface SZJsonParser : NSObject 12 | { 13 | NSString *mSource; 14 | NSUInteger mLength; 15 | NSUInteger mPos; 16 | } 17 | 18 | - (id)initWithSource:(NSString *)source; 19 | - (id)parse; 20 | 21 | @end 22 | 23 | @interface NSString (JsonParser) 24 | 25 | - (id)jsonObject; 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/VMMAlert.h: -------------------------------------------------------------------------------- 1 | // 2 | // VMMAlert.h 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 22/02/17. 6 | // Copyright © 2017 Vitor Marques de Miranda. All rights reserved. 7 | // 8 | 9 | #ifndef VMMAlert_Extension_Class 10 | #define VMMAlert_Extension_Class 11 | 12 | #import 13 | 14 | /*! 15 | * @typedef VMMAlertType 16 | * @brief A list of predefined alert types. 17 | * @constant VMMAlertTypeSuccess An alert with 'Success' as title and the default alert icon. 18 | * @constant VMMAlertTypeWarning An alert with 'Warning' as title and the NSCriticalAlertStyle icon. 19 | * @constant VMMAlertTypeError An alert with 'Error' as title and NSImageNameCaution as icon. 20 | * @constant VMMAlertTypeCritical An alert with 'Error' as title and NSImageNameStopProgressFreestandingTemplate as icon. 21 | * @constant VMMAlertTypeCustom An alert with the app name as title and the default alert icon. 22 | */ 23 | typedef enum VMMAlertType 24 | { 25 | /// An alert with 'Success' as title and the default alert icon. 26 | VMMAlertTypeSuccess, 27 | 28 | /// An alert with 'Warning' as title and the NSCriticalAlertStyle icon. 29 | VMMAlertTypeWarning, 30 | 31 | /// An alert with 'Error' as title and NSImageNameCaution as icon. 32 | VMMAlertTypeError, 33 | 34 | /// An alert with 'Error' as title and NSImageNameStopProgressFreestandingTemplate as icon. 35 | VMMAlertTypeCritical, 36 | 37 | /// An alert with the app name as title and the default alert icon. 38 | VMMAlertTypeCustom 39 | } VMMAlertType; 40 | 41 | @interface VMMAlert : NSAlert 42 | 43 | /*! 44 | * @discussion Changes the icon of a VMMAlert based in the VMMAlertType. 45 | * @param alertType The VMMAlertType that will be used to configure the alert icon. 46 | */ 47 | -(void)setIconWithAlertType:(VMMAlertType)alertType; 48 | 49 | /*! 50 | * @discussion Same as runModal, but which runs the alert in the main thread and returns the result to the active thread. 51 | * @discussion This method is thread safe, so it can be used from any thread or queue. 52 | * @return The runModal output. 53 | */ 54 | -(NSUInteger)runThreadSafeModal; 55 | 56 | /*! 57 | * @discussion Same as runModal, but which creates and runs the alert in the main thread and returns the result to the active thread. 58 | * @discussion This method is thread safe, so it can be used from any thread or queue. 59 | * @param alert A block that will be run in the main thread, and needs as return the VMMAlert that will be shown. 60 | * @return The runModal output. 61 | */ 62 | +(NSUInteger)runThreadSafeModalWithAlert:(VMMAlert* (^)(void))alert; 63 | 64 | /*! 65 | * @discussion Shows a VMMAlert with the contents of a NSException and an Ok button. 66 | * @discussion This method is thread safe, so it can be used from any thread or queue. 67 | * @param exception The exception that will be used to create the alert. 68 | */ 69 | +(void)showErrorAlertWithException:(NSException*)exception; 70 | 71 | /*! 72 | * @discussion Shows a VMMAlert with a predefined VMMAlertType, an informative text and an Ok button. 73 | * @discussion This method is thread safe, so it can be used from any thread or queue. 74 | * @param alertType The VMMAlertType that will be used to configure the alert. 75 | * @param message The message (aka. informative text) that will be shown in the alert. 76 | */ 77 | +(void)showAlertOfType:(VMMAlertType)alertType withMessage:(NSString*)message; 78 | 79 | /*! 80 | * @discussion Shows a VMMAlert with a title, an informative text, any other configurations specified in the block and an Ok button. 81 | * @discussion This method is thread safe, so it can be used from any thread or queue. 82 | * @param title The title that will be shown in the alert. 83 | * @param message The message (aka. informative text) that will be shown in the alert. 84 | * @param optionsForAlert The block to make any extra adjustments in the alert before showing it. 85 | */ 86 | +(void)showAlertWithTitle:(NSString*)title message:(NSString*)message andSettings:(void (^)(VMMAlert* alert))optionsForAlert; 87 | 88 | /*! 89 | * @discussion Shows a VMMAlert with a title, a subtitle, an attributed informative text and an Ok button. 90 | * @discussion This method is thread safe, so it can be used from any thread or queue. 91 | * @param title The title that will be shown in the alert. 92 | * @param subtitle The subtitle (aka. informative text) that will be shown in the alert. 93 | * @param message The message (aka. attributed informative text) that will be shown in the alert. 94 | * @param fixedWidth The width of the message area that will be shown in the alert (0 to use the real message width). 95 | */ 96 | +(void)showAlertWithTitle:(NSString*)title subtitle:(NSString*)subtitle andAttributedMessage:(NSAttributedString*)message withWidth:(CGFloat)fixedWidth; 97 | 98 | /*! 99 | * @discussion Shows a VMMAlert with a title, an informative text and Yes/No buttons. 100 | * @discussion This method is thread safe, so it can be used from any thread or queue. 101 | * @param title The title that will be shown in the alert. 102 | * @param message The message (aka. informative text) that will be shown in the alert. 103 | * @param highlight The button that will be highlighted by default in the alert (Yes/No). 104 | * @return true if Yes was pressed, false if No was pressed. 105 | */ 106 | +(BOOL)showBooleanAlertWithTitle:(NSString*)title message:(NSString*)message highlighting:(BOOL)highlight; 107 | 108 | /*! 109 | * @discussion Shows a VMMAlert with a predefined VMMAlertType, an informative text and Yes/No buttons. 110 | * @discussion This method is thread safe, so it can be used from any thread or queue. 111 | * @param alertType The VMMAlertType that will be used to configure the alert. 112 | * @param message The message (aka. informative text) that will be shown in the alert. 113 | * @param highlight The button that will be highlighted by default in the alert (Yes/No). 114 | * @return true if Yes was pressed, false if No was pressed. 115 | */ 116 | +(BOOL)showBooleanAlertOfType:(VMMAlertType)alertType withMessage:(NSString*)message highlighting:(BOOL)highlight; 117 | 118 | /*! 119 | * @discussion Shows a VMMAlert with a title, an informative text, any other configurations specified in the block and Yes/No buttons. 120 | * @discussion This method is thread safe, so it can be used from any thread or queue. 121 | * @param title The title that will be shown in the alert. 122 | * @param message The message (aka. informative text) that will be shown in the alert. 123 | * @param highlight The button that will be highlighted by default in the alert (Yes/No). 124 | * @param optionsForAlert The block to make any extra adjustments in the alert before showing it. 125 | * @return true if Yes was pressed, false if No was pressed. 126 | */ 127 | +(BOOL)showBooleanAlertWithTitle:(NSString*)title message:(NSString*)message highlighting:(BOOL)highlight withSettings:(void (^)(VMMAlert* alert))optionsForAlert; 128 | 129 | /*! 130 | * @discussion Shows a VMMAlert with a title, an informative text, any other configurations specified in the block and Ok/Cancel buttons. 131 | * @discussion This method is thread safe, so it can be used from any thread or queue. 132 | * @param message The message (aka. informative text) that will be shown in the alert. 133 | * @param prompt The title that will be shown in the alert. 134 | * @param optionsForAlert The block to make any extra adjustments in the alert before showing it. 135 | * @return true if Ok was pressed, false if Cancel was pressed. 136 | */ 137 | +(BOOL)confirmationDialogWithTitle:(NSString*)prompt message:(NSString*)message andSettings:(void (^)(VMMAlert* alert))optionsForAlert; 138 | 139 | /*! 140 | * @discussion Shows a VMMAlert with a title, an informative text, a text field and Ok/Cancel buttons. 141 | * @discussion This method is thread safe, so it can be used from any thread or queue. 142 | * @param prompt The title that will be shown in the alert. 143 | * @param message The message (aka. informative text) that will be shown in the alert. 144 | * @param defaultValue The initial string value of the text field. 145 | * @return The string value of the text field if Ok was pressed, nil if Cancel was pressed. 146 | */ 147 | +(NSString*)inputDialogWithTitle:(NSString*)prompt message:(NSString*)message defaultValue:(NSString*)defaultValue; 148 | 149 | /*! 150 | * @discussion Shows a VMMAlert with a title, an informative text, big squared buttons and a Cancel button. 151 | * @discussion This method is thread safe, so it can be used from any thread or queue. 152 | * @param title The title that will be shown in the alert. 153 | * @param message The message (aka. informative text) that will be shown in the alert. 154 | * @param options The list of the buttons that should appear in the dialog. 155 | * @param iconForOption A block that needs as return the image that will be the icon for each button title. 156 | * @return The title of the pressed big button if any was pressed, nil if Cancel was pressed. 157 | */ 158 | +(NSString*)showAlertWithTitle:(NSString*)title message:(NSString*)message buttonOptions:(NSArray*)options andIconForEachOption:(NSImage* (^)(NSString* option))iconForOption; 159 | 160 | @end 161 | 162 | #endif 163 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/VMMDeviceObserver.h: -------------------------------------------------------------------------------- 1 | // 2 | // VMMDeviceObserver.h 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 09/08/17. 6 | // Copyright © 2017 Vitor Marques de Miranda. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import 12 | #import 13 | #include 14 | 15 | #define VMMDeviceObserverTypesKeyboard @[@(kHIDUsage_GD_Keyboard), @(kHIDUsage_GD_Keypad)] 16 | #define VMMDeviceObserverTypesJoystick @[@(kHIDUsage_GD_Joystick), @(kHIDUsage_GD_GamePad), @(kHIDUsage_GD_MultiAxisController)] 17 | 18 | static int const IOHIDMaxIntegerValueBytes = 4; 19 | 20 | BOOL IOHIDDeviceGetLongProperty(IOHIDDeviceRef _Nullable inIOHIDDeviceRef, CFStringRef _Nonnull inKey, long * _Nonnull outValue); 21 | long IOHIDDeviceGetUsage(IOHIDDeviceRef _Nullable device); 22 | long IOHIDDeviceGetVendorID(IOHIDDeviceRef _Nullable device); 23 | 24 | @protocol VMMDeviceObserverDelegate 25 | 26 | @property (nonatomic, nullable) IOHIDManagerRef hidManager; 27 | 28 | @optional 29 | 30 | -(void)observedConnectionOfDevice:(nonnull IOHIDDeviceRef)device; 31 | -(void)observedRemovalOfDevice:(nonnull IOHIDDeviceRef)device; 32 | -(void)observedEventWithName:(nullable CFStringRef)name cookie:(IOHIDElementCookie)cookie usage:(uint32_t)usage value:(CFIndex)value device:(nonnull IOHIDDeviceRef)device; 33 | -(void)observedReportWithID:(uint32_t)reportID data:(nonnull uint8_t*)report type:(IOHIDReportType)reportType length:(CFIndex)reportLength device:(nonnull IOHIDDeviceRef)device; 34 | -(CFIndex)receivedPacketMaxSize; 35 | 36 | @end 37 | 38 | 39 | @interface VMMDeviceObserver : NSObject 40 | 41 | +(nonnull instancetype)sharedObserver; 42 | -(BOOL)observeDevicesOfTypes:(nonnull NSArray*)types forDelegate:(nonnull id)actionDelegate; 43 | -(BOOL)stopObservingForDelegate:(nonnull id)actionDelegate; 44 | 45 | @property (nonatomic) uint8_t* _Nullable receivedReport; 46 | 47 | @end 48 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/VMMDeviceObserver.m: -------------------------------------------------------------------------------- 1 | // 2 | // VMMDeviceObserver.m 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 09/08/17. 6 | // Copyright © 2017 Vitor Marques de Miranda. All rights reserved. 7 | // 8 | 9 | #import "VMMDeviceObserver.h" 10 | 11 | #import "NSArray+Extension.h" 12 | #import "NSMutableArray+Extension.h" 13 | 14 | #import "VMMLogUtility.h" 15 | 16 | BOOL IOHIDDeviceGetLongProperty(IOHIDDeviceRef _Nullable inIOHIDDeviceRef, CFStringRef _Nonnull inKey, long * _Nonnull outValue) 17 | { 18 | BOOL result = FALSE; 19 | if (inIOHIDDeviceRef) 20 | { 21 | assert(IOHIDDeviceGetTypeID() == CFGetTypeID(inIOHIDDeviceRef)); 22 | 23 | CFTypeRef tCFTypeRef = IOHIDDeviceGetProperty(inIOHIDDeviceRef, inKey); 24 | if (tCFTypeRef) 25 | { 26 | if (CFNumberGetTypeID() == CFGetTypeID(tCFTypeRef)) 27 | { 28 | result = CFNumberGetValue((CFNumberRef)tCFTypeRef, kCFNumberSInt32Type, outValue); 29 | } 30 | } 31 | } 32 | 33 | return result; 34 | } 35 | long IOHIDDeviceGetUsage(IOHIDDeviceRef _Nullable device) 36 | { 37 | long result = 0; 38 | IOHIDDeviceGetLongProperty(device, CFSTR(kIOHIDPrimaryUsageKey), &result); 39 | return result; 40 | } 41 | long IOHIDDeviceGetVendorID(IOHIDDeviceRef _Nullable device) 42 | { 43 | long vendorID = 0; 44 | IOHIDDeviceGetLongProperty(device, CFSTR(kIOHIDVendorIDKey), &vendorID); 45 | return vendorID; 46 | } 47 | 48 | @implementation VMMDeviceObserver 49 | 50 | +(nonnull instancetype)sharedObserver 51 | { 52 | static VMMDeviceObserver* sharedObserver = nil; 53 | static dispatch_once_t onceToken; 54 | 55 | dispatch_once(&onceToken, ^{ 56 | sharedObserver = [[VMMDeviceObserver alloc] init]; 57 | }); 58 | 59 | return sharedObserver; 60 | } 61 | 62 | -(BOOL)observeDevicesOfTypes:(nonnull NSArray*)types forDelegate:(nonnull id)actionDelegate 63 | { 64 | if (actionDelegate.hidManager != NULL) { 65 | [self stopObservingForDelegate:actionDelegate]; 66 | } 67 | 68 | actionDelegate.hidManager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); 69 | 70 | NSMutableArray* deviceTypes = [types map:^id(id object) { 71 | return @{@(kIOHIDDeviceUsagePageKey): @(kHIDPage_GenericDesktop), @(kIOHIDDeviceUsageKey): object}; 72 | }]; 73 | 74 | IOHIDManagerSetDeviceMatchingMultiple(actionDelegate.hidManager, (__bridge CFArrayRef)deviceTypes); 75 | 76 | IOHIDManagerRegisterDeviceMatchingCallback(actionDelegate.hidManager, &Handle_DeviceMatchingCallback, (__bridge void*)actionDelegate); 77 | IOHIDManagerRegisterDeviceRemovalCallback (actionDelegate.hidManager, &Handle_DeviceRemovalCallback, (__bridge void*)actionDelegate); 78 | 79 | IOHIDManagerScheduleWithRunLoop(actionDelegate.hidManager, CFRunLoopGetMain(), kCFRunLoopDefaultMode); 80 | 81 | IOReturn IOReturn = IOHIDManagerOpen(actionDelegate.hidManager, kIOHIDOptionsTypeNone); 82 | 83 | IOHIDManagerRegisterInputValueCallback(actionDelegate.hidManager, Handle_DeviceEventCallback, (__bridge void*)actionDelegate); 84 | 85 | return (IOReturn == kIOReturnSuccess); 86 | } 87 | -(BOOL)stopObservingForDelegate:(nonnull id)actionDelegate 88 | { 89 | if (actionDelegate.hidManager == NULL) return true; 90 | 91 | IOReturn IOReturn = IOHIDManagerClose(actionDelegate.hidManager, kIOHIDOptionsTypeNone); 92 | actionDelegate.hidManager = NULL; 93 | 94 | return (IOReturn == kIOReturnSuccess); 95 | } 96 | 97 | static void Handle_DeviceMatchingCallback(void *inContext, IOReturn inResult, void *inSender, IOHIDDeviceRef inIOHIDDeviceRef) 98 | { 99 | if (inIOHIDDeviceRef == NULL) return; 100 | 101 | VMMDeviceObserver* sender = VMMDeviceObserver.sharedObserver; 102 | 103 | NSObject* actionDelegate = (__bridge NSObject*)inContext; 104 | if (![actionDelegate respondsToSelector:@selector(observedConnectionOfDevice:)]) return; 105 | 106 | if ([actionDelegate respondsToSelector:@selector(receivedPacketMaxSize)]) 107 | { 108 | sender.receivedReport = (uint8_t *)calloc(actionDelegate.receivedPacketMaxSize, sizeof(uint8_t)); 109 | 110 | IOHIDDeviceScheduleWithRunLoop(inIOHIDDeviceRef, CFRunLoopGetMain(), kCFRunLoopCommonModes); 111 | IOHIDDeviceRegisterInputReportCallback(inIOHIDDeviceRef, sender.receivedReport, actionDelegate.receivedPacketMaxSize, 112 | Handle_DeviceReportCallback, inContext); 113 | } 114 | 115 | [actionDelegate observedConnectionOfDevice:inIOHIDDeviceRef]; 116 | } 117 | static void Handle_DeviceRemovalCallback (void *inContext, IOReturn inResult, void *inSender, IOHIDDeviceRef inIOHIDDeviceRef) 118 | { 119 | if (inIOHIDDeviceRef == NULL) return; 120 | 121 | NSObject* actionDelegate = (__bridge NSObject*)inContext; 122 | if (![actionDelegate respondsToSelector:@selector(observedRemovalOfDevice:)]) return; 123 | 124 | [actionDelegate observedRemovalOfDevice:inIOHIDDeviceRef]; 125 | } 126 | static void Handle_DeviceEventCallback (void *inContext, IOReturn inResult, void *inSender, IOHIDValueRef value) 127 | { 128 | IOHIDElementRef element = IOHIDValueGetElement(value); // Pressed key 129 | if (element == NULL) return; 130 | 131 | IOHIDDeviceRef device = IOHIDElementGetDevice(element); // Device 132 | if (device == NULL) return; 133 | 134 | CFIndex elementValue = -1; 135 | if (IOHIDValueGetLength(value) <= IOHIDMaxIntegerValueBytes) 136 | { 137 | // 138 | // If the size of the package is bigger than 4 bytes, IOHIDValueGetIntegerValue() will cause 139 | // a SEGFAULT exception. That should solve the crash caused by that exception, since that 140 | // kind of exception can't be caught by a try/catch. 141 | // 142 | // https://github.com/nagyistoce/macifom/issues/3 143 | // https://groups.google.com/forum/#!topic/pyglet-users/O3RuDqmYr5Y 144 | // 145 | 146 | elementValue = IOHIDValueGetIntegerValue(value); // Actual state of the pressed key 147 | } 148 | 149 | IOHIDElementCookie cookie = IOHIDElementGetCookie(element); // Cookie of the pressed key 150 | uint32_t usage = IOHIDElementGetUsage(element); // Usage of the pressed key 151 | CFStringRef name = IOHIDElementGetName(element); 152 | 153 | NSObject* actionDelegate = (__bridge NSObject*)inContext; 154 | if (actionDelegate == nil) return; 155 | if (![actionDelegate respondsToSelector:@selector(observedEventWithName:cookie:usage:value:device:)]) return; 156 | 157 | [actionDelegate observedEventWithName:name cookie:cookie usage:usage value:elementValue device:device]; 158 | } 159 | 160 | static void Handle_DeviceReportCallback (void* context, IOReturn result, void* sender, IOHIDReportType type, uint32_t reportID, uint8_t* report, CFIndex reportLength) 161 | { 162 | IOHIDDeviceRef device = (IOHIDDeviceRef)sender; 163 | 164 | NSObject* actionDelegate = (__bridge NSObject*)context; 165 | if (actionDelegate == nil) return; 166 | if (![actionDelegate respondsToSelector:@selector(observedReportWithID:data:type:length:device:)]) return; 167 | 168 | [actionDelegate observedReportWithID:reportID data:report type:type length:reportLength device:device]; 169 | } 170 | 171 | @end 172 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/VMMDeviceSimulator.h: -------------------------------------------------------------------------------- 1 | // 2 | // VMMDeviceSimulator.h 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 01/10/2017. 6 | // Copyright © 2017 VitorMM. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface VMMDeviceSimulator : NSObject 12 | 13 | +(void)simulateCursorClickAtScreenPoint:(CGPoint)clickPoint; 14 | 15 | +(void)simulateVirtualKeycode:(CGKeyCode)keyCode withKeyDown:(BOOL)keyPressed; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/VMMDeviceSimulator.m: -------------------------------------------------------------------------------- 1 | // 2 | // VMMDeviceSimulator.m 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 01/10/2017. 6 | // Copyright © 2017 VitorMM. All rights reserved. 7 | // 8 | // Reference: 9 | // https://stackoverflow.com/questions/28485257/objective-c-mac-os-x-simulate-a-mouse-click-event-onto-a-specific-applicatio 10 | // 11 | 12 | #import "VMMDeviceSimulator.h" 13 | 14 | @implementation VMMDeviceSimulator 15 | 16 | +(void)simulateCursorClickAtScreenPoint:(CGPoint)clickPoint 17 | { 18 | // TODO: In macOS Mojave, the method below requires accessibility permissions. 19 | // https://objective-see.com/blog/blog_0x36.html 20 | // https://forums.developer.apple.com/thread/105667 21 | // 22 | // Still couldn't find a suitable workaround for requiring the permission 23 | // a second time in case the user denied by mistake. 24 | 25 | CGEventRef theEvent = CGEventCreateMouseEvent(NULL, kCGEventLeftMouseDown, clickPoint, kCGMouseButtonLeft); 26 | CGEventPost(kCGHIDEventTap, theEvent); 27 | CGEventSetType(theEvent, kCGEventLeftMouseUp); 28 | CGEventPost(kCGHIDEventTap, theEvent); 29 | 30 | CGEventSetIntegerValueField(theEvent, kCGMouseEventClickState, 2); 31 | 32 | CGEventSetType(theEvent, kCGEventLeftMouseDown); 33 | CGEventPost(kCGHIDEventTap, theEvent); 34 | 35 | CGEventSetType(theEvent, kCGEventLeftMouseUp); 36 | CGEventPost(kCGHIDEventTap, theEvent); 37 | 38 | CFRelease(theEvent); 39 | } 40 | 41 | +(void)simulateVirtualKeycode:(CGKeyCode)keyCode withKeyDown:(BOOL)keyPressed 42 | { 43 | CGEventRef cmdd = CGEventCreateKeyboardEvent(NULL, keyCode, keyPressed); 44 | CGEventPost(kCGHIDEventTap, cmdd); 45 | CFRelease(cmdd); 46 | } 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/VMMDockProgressIndicator.h: -------------------------------------------------------------------------------- 1 | // 2 | // VMMDockProgressIndicator.h 3 | // ObjectiveC_Extension 4 | // 5 | // Copyright (c) 2014, hokein 6 | // All rights reserved. 7 | // 8 | // Redistribution and use in source and binary forms, with or without 9 | // modification, are permitted provided that the following conditions are met: 10 | // * Redistributions of source code must retain the above copyright 11 | // notice, this list of conditions and the following disclaimer. 12 | // * Redistributions in binary form must reproduce the above copyright 13 | // notice, this list of conditions and the following disclaimer in the 14 | // documentation and/or other materials provided with the distribution. 15 | // * Neither the name of the nor the 16 | // names of its contributors may be used to endorse or promote products 17 | // derived from this software without specific prior written permission. 18 | 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | // DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 23 | // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 | // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | // Reference: 31 | // https://github.com/hokein/DockProgressBar 32 | // 33 | 34 | #import 35 | 36 | @interface VMMDockProgressIndicator : NSProgressIndicator 37 | 38 | + (nonnull VMMDockProgressIndicator*)sharedInstance; 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/VMMDockProgressIndicator.m: -------------------------------------------------------------------------------- 1 | // 2 | // VMMDockProgressIndicator.m 3 | // ObjectiveC_Extension 4 | // 5 | // Copyright (c) 2014, hokein 6 | // All rights reserved. 7 | // 8 | // Redistribution and use in source and binary forms, with or without 9 | // modification, are permitted provided that the following conditions are met: 10 | // * Redistributions of source code must retain the above copyright 11 | // notice, this list of conditions and the following disclaimer. 12 | // * Redistributions in binary form must reproduce the above copyright 13 | // notice, this list of conditions and the following disclaimer in the 14 | // documentation and/or other materials provided with the distribution. 15 | // * Neither the name of the nor the 16 | // names of its contributors may be used to endorse or promote products 17 | // derived from this software without specific prior written permission. 18 | 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | // DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 23 | // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 | // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | // Reference: 31 | // https://github.com/hokein/DockProgressBar 32 | // 33 | 34 | #import "VMMDockProgressIndicator.h" 35 | 36 | #import "NSBundle+Extension.h" 37 | #import "NSColor+Extension.h" 38 | 39 | @implementation VMMDockProgressIndicator 40 | 41 | static VMMDockProgressIndicator* progress_bar; 42 | 43 | + (nonnull VMMDockProgressIndicator*)sharedInstance 44 | { 45 | NSDockTile* dock_tile = [NSApp dockTile]; 46 | 47 | if (!progress_bar) 48 | { 49 | progress_bar = [[VMMDockProgressIndicator alloc] initWithFrame:NSMakeRect(0.0f, 0.0f, dock_tile.size.width, 15.0f)]; 50 | [progress_bar setStyle:NSProgressIndicatorBarStyle]; 51 | [progress_bar setIndeterminate:NO]; 52 | [progress_bar setBezeled:YES]; 53 | [progress_bar setMinValue:0]; 54 | [progress_bar setMaxValue:1]; 55 | } 56 | 57 | if (dock_tile.contentView == nil) 58 | { 59 | NSImage* contentViewImage; 60 | 61 | @try 62 | { 63 | contentViewImage = [NSApp applicationIconImage]; 64 | } 65 | @catch(NSException* exception) 66 | { 67 | NSBundle* mainBundle = [NSBundle originalMainBundle]; 68 | 69 | @try 70 | { 71 | contentViewImage = [mainBundle bundleIcon]; 72 | } 73 | @catch(NSException* otherException) 74 | { 75 | [exception raise]; 76 | } 77 | } 78 | 79 | NSImageView* contentView = [[NSImageView alloc] init]; 80 | [contentView setImage:contentViewImage]; 81 | [dock_tile setContentView:contentView]; 82 | [contentView addSubview:progress_bar]; 83 | } 84 | 85 | return progress_bar; 86 | } 87 | 88 | - (void)drawRect:(NSRect)dirtyRect 89 | { 90 | NSRect rect = NSInsetRect(self.bounds, 1.0, 1.0); 91 | CGFloat radius = rect.size.height / 2; 92 | NSBezierPath* bezier_path = [NSBezierPath bezierPathWithRoundedRect:rect xRadius:radius yRadius:radius]; 93 | [bezier_path setLineWidth:2.0]; 94 | [[NSColor grayColor] set]; 95 | [bezier_path stroke]; 96 | 97 | // Fill the rounded rect. 98 | rect = NSInsetRect(rect, 2.0, 2.0); 99 | radius = rect.size.height / 2; 100 | bezier_path = [NSBezierPath bezierPathWithRoundedRect:rect xRadius:radius yRadius:radius]; 101 | [bezier_path setLineWidth:1.0]; 102 | [bezier_path addClip]; 103 | 104 | // Calculate the progress width. 105 | rect.size.width = floor(rect.size.width * ((self.doubleValue - self.minValue) / (self.maxValue - self.minValue))); 106 | 107 | // Fill the progress bar with color blue. 108 | [RGB(51, 153, 255) set]; 109 | NSRectFill(rect); 110 | } 111 | 112 | - (void)setHidden:(BOOL)hidden 113 | { 114 | [super setHidden:hidden]; 115 | [[NSApp dockTile] display]; 116 | } 117 | 118 | - (void)setDoubleValue:(double)doubleValue 119 | { 120 | [super setDoubleValue:doubleValue]; 121 | [[NSApp dockTile] display]; 122 | } 123 | 124 | @end 125 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/VMMKeyCaptureField.h: -------------------------------------------------------------------------------- 1 | // 2 | // VMMKeyCaptureField.h 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 18/08/17. 6 | // Copyright © 2017 Vitor Marques de Miranda. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "VMMDeviceObserver.h" 12 | #import "VMMUsageKeycode.h" 13 | 14 | @protocol VMMKeyCaptureFieldDelegate 15 | -(void)keyCaptureField:(nonnull NSTextField*)field didChangedKeyUsageKeycode:(uint32_t)keyUsage; 16 | @end 17 | 18 | @interface VMMKeyCaptureField : NSTextField 19 | 20 | @property (nonatomic, strong, nullable) IBOutlet NSObject* keyCaptureDelegate; 21 | @property (nonatomic, nullable) IOHIDManagerRef hidManager; 22 | @property (nonatomic) uint32_t keyUsageKeycode; 23 | 24 | @end 25 | 26 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/VMMKeyCaptureField.m: -------------------------------------------------------------------------------- 1 | // 2 | // VMMKeyCaptureField.m 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 18/08/17. 6 | // Copyright © 2017 Vitor Marques de Miranda. All rights reserved. 7 | // 8 | 9 | #import "VMMKeyCaptureField.h" 10 | 11 | #import "VMMUsageKeycode.h" 12 | #import "VMMLocalizationUtility.h" 13 | 14 | static VMMKeyCaptureField* _activeKeyCaptureField; 15 | 16 | @implementation VMMKeyCaptureField 17 | 18 | -(void)awakeFromNib 19 | { 20 | _keyUsageKeycode = -1; 21 | _activeKeyCaptureField = nil; 22 | } 23 | 24 | -(void)startEditing 25 | { 26 | if (_activeKeyCaptureField) 27 | { 28 | if (_activeKeyCaptureField == self) return; 29 | 30 | [VMMDeviceObserver.sharedObserver stopObservingForDelegate:_activeKeyCaptureField]; 31 | } 32 | 33 | _activeKeyCaptureField = self; 34 | [VMMDeviceObserver.sharedObserver observeDevicesOfTypes:VMMDeviceObserverTypesKeyboard forDelegate:self]; 35 | } 36 | -(void)stopEditing 37 | { 38 | if (_activeKeyCaptureField == self) 39 | { 40 | _activeKeyCaptureField = nil; 41 | } 42 | 43 | [VMMDeviceObserver.sharedObserver stopObservingForDelegate:self]; 44 | } 45 | 46 | -(BOOL)textShouldBeginEditing:(NSText *)textObject 47 | { 48 | return false; 49 | } 50 | -(void)textDidEndEditing:(NSNotification *)notification 51 | { 52 | [self stopEditing]; 53 | } 54 | 55 | -(BOOL)becomeFirstResponder 56 | { 57 | BOOL result = [super becomeFirstResponder]; 58 | if (result) [self startEditing]; 59 | return result; 60 | } 61 | -(BOOL)resignFirstResponder 62 | { 63 | BOOL result = [super resignFirstResponder]; 64 | if (result) [self stopEditing]; 65 | return result; 66 | } 67 | 68 | -(void)observedEventWithName:(CFStringRef)name cookie:(IOHIDElementCookie)cookie usage:(uint32_t)usage 69 | value:(CFIndex)value device:(IOHIDDeviceRef)device 70 | { 71 | if (!self.window.isKeyWindow) return; 72 | if (![[self.window firstResponder] isKindOfClass:NSText.class]) return; 73 | 74 | if (_activeKeyCaptureField != self) return; 75 | if (value != 1) return; 76 | 77 | // Exception 78 | if (usage == 128 && cookie == 242) return; // Logitech G600 Mouse Left-button click 79 | if (usage == 128 && cookie == 243) return; // Logitech G600 Mouse Middle-button click 80 | if (usage == 128 && cookie == 244) return; // Logitech G600 Mouse Right-button click 81 | 82 | dispatch_async(dispatch_get_main_queue(), ^ 83 | { 84 | [self setKeyUsageKeycode:usage]; 85 | 86 | if (self->_keyCaptureDelegate) 87 | { 88 | [self->_keyCaptureDelegate keyCaptureField:self didChangedKeyUsageKeycode:usage]; 89 | } 90 | }); 91 | } 92 | 93 | -(void)setKeyUsageKeycode:(uint32_t)keyUsageKeycode 94 | { 95 | if (keyUsageKeycode == -1) 96 | { 97 | _keyUsageKeycode = -1; 98 | [self setStringValue:@""]; 99 | return; 100 | } 101 | 102 | _keyUsageKeycode = keyUsageKeycode; 103 | NSString* keyName = [VMMUsageKeycode nameOfUsageKeycode:keyUsageKeycode]; 104 | [self setStringValue:keyName ? keyName : [NSString stringWithFormat:VMMLocalizedString(@"Unknown Key (%d)"),keyUsageKeycode]]; 105 | } 106 | 107 | -(IBAction)clearField:(id)sender 108 | { 109 | _keyUsageKeycode = -1; 110 | [self setStringValue:@""]; 111 | 112 | if (_keyCaptureDelegate) 113 | { 114 | [_keyCaptureDelegate keyCaptureField:self didChangedKeyUsageKeycode:_keyUsageKeycode]; 115 | } 116 | } 117 | 118 | @end 119 | 120 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/VMMLocalizationUtility.h: -------------------------------------------------------------------------------- 1 | // 2 | // VMMLocalizationUtility.h 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 06/12/2017. 6 | // Copyright © 2017 VitorMM. All rights reserved. 7 | // 8 | 9 | #define VMMLocalizationNotNeeded(S) [NSMutableString stringWithString:S] 10 | #define VMMLocalizedString(S) NSLocalizedString(S, nil) 11 | 12 | 13 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/VMMLogUtility.h: -------------------------------------------------------------------------------- 1 | // 2 | // VMMLogUtility.h 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 31/07/2017. 6 | // Copyright © 2017 Vitor Marques de Miranda. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "ObjCExtensionConfig.h" 11 | #import "NSString+Extension.h" 12 | 13 | #ifdef DEBUG 14 | #if NSDEBUGLOG_SHOULD_PRINT_TO_A_DESKTOP_FILE_TOO == true 15 | #define NSDebugLog(FORMAT, ...) system([[NSString stringWithFormat:@"echo \"%@\" | tee -a ~/Desktop/debug.log", [[[[NSString stringWithFormat:FORMAT, ##__VA_ARGS__] stringByReplacingOccurrencesOfString:@"\"" withString:@"\\\""] stringByReplacingOccurrencesOfString:@"\n" withString:@"\\n"] stringByRemovingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"\0"]]] UTF8String]) 16 | #else 17 | #define NSDebugLog(FORMAT, ...) system([[NSString stringWithFormat:@"echo \"%@\"", [[[[NSString stringWithFormat:FORMAT, ##__VA_ARGS__] stringByReplacingOccurrencesOfString:@"\"" withString:@"\\\""] stringByReplacingOccurrencesOfString:@"\n" withString:@"\\n"] stringByRemovingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"\0"]]] UTF8String]) 18 | #endif 19 | #else 20 | #define NSDebugLog(...) 21 | #endif 22 | 23 | void NSStackTraceLog(void); 24 | 25 | // Source: 26 | // https://gist.github.com/sfider/3072143 27 | 28 | #define measureTime(__message) \ 29 | for (CFAbsoluteTime startTime##__LINE__ = CFAbsoluteTimeGetCurrent(), endTime##__LINE__ = 0.0; endTime##__LINE__ == 0.0; \ 30 | NSDebugLog(@"'%@' took %.6fs", (__message), (endTime##__LINE__ = CFAbsoluteTimeGetCurrent()) - startTime##__LINE__)) 31 | 32 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/VMMLogUtility.m: -------------------------------------------------------------------------------- 1 | // 2 | // VMMLogUtility.m 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 19/12/2017. 6 | // Copyright © 2017 VitorMM. All rights reserved. 7 | // 8 | 9 | #import "VMMLogUtility.h" 10 | 11 | void NSStackTraceLog(void) 12 | { 13 | NSDebugLog(@"%@",[NSThread callStackSymbols]); 14 | } 15 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/VMMMenu.h: -------------------------------------------------------------------------------- 1 | // 2 | // VMMMenu.h 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 03/02/19. 6 | // Copyright © 2019 VitorMM. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface VMMMenu : NSMenu 14 | 15 | + (void)forceLightMenu; 16 | + (void)forceDarkMenu; 17 | + (void)forceSystemMenu; 18 | 19 | @end 20 | 21 | NS_ASSUME_NONNULL_END 22 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/VMMMenu.m: -------------------------------------------------------------------------------- 1 | // 2 | // VMMMenu.m 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 03/02/19. 6 | // Copyright © 2019 VitorMM. All rights reserved. 7 | // 8 | 9 | #import "VMMMenu.h" 10 | 11 | #import 12 | #import 13 | 14 | #if __LP64__ 15 | extern void SetMenuItemProperty(MenuRef menu, 16 | MenuItemIndex item, 17 | OSType propertyCreator, 18 | OSType propertyTag, 19 | ByteCount propertySize, 20 | const void * propertyData); 21 | #endif 22 | 23 | 24 | @interface NSMenu (Private) 25 | - (id)_menuImpl; 26 | @end 27 | 28 | 29 | @protocol NSCarbonMenuImplProtocol 30 | - (MenuRef)_principalMenuRef; 31 | @end 32 | 33 | 34 | @interface NSMenu (DarkPrivate) 35 | - (void)makeDark; 36 | @end 37 | 38 | 39 | @interface NSMenuDarkMaker : NSObject 40 | { 41 | NSMenu * mMenu; 42 | } 43 | - (id)initWithMenu:(NSMenu *)menu; 44 | @end 45 | 46 | @implementation VMMMenu 47 | 48 | static int MAKE_DARK_KEY; 49 | 50 | static BOOL FORCE_LIGHT; 51 | static BOOL FORCE_DARK; 52 | 53 | + (void)forceLightMenu { 54 | FORCE_LIGHT = true; 55 | FORCE_DARK = false; 56 | } 57 | + (void)forceDarkMenu { 58 | FORCE_LIGHT = false; 59 | FORCE_DARK = true; 60 | } 61 | + (void)forceSystemMenu { 62 | FORCE_LIGHT = false; 63 | FORCE_DARK = false; 64 | } 65 | 66 | -(instancetype)init 67 | { 68 | self = [super init]; 69 | if (self) { 70 | NSMenuDarkMaker * maker = [[NSMenuDarkMaker alloc] initWithMenu:self]; 71 | objc_setAssociatedObject(self, &MAKE_DARK_KEY, maker, OBJC_ASSOCIATION_RETAIN); 72 | } 73 | return self; 74 | } 75 | 76 | - (void)makeDark 77 | { 78 | if (FORCE_LIGHT || FORCE_DARK) 79 | { 80 | id impl = [self _menuImpl]; 81 | if ([impl respondsToSelector:@selector(_principalMenuRef)]) { 82 | MenuRef m = [impl _principalMenuRef]; 83 | if (m) { 84 | char on = FORCE_DARK ? 1 : 0; 85 | SetMenuItemProperty(m, 0, 'dock', 'dark', 1, &on); 86 | } 87 | } 88 | 89 | for (NSMenuItem * item in self.itemArray) 90 | { 91 | [item.submenu makeDark]; 92 | } 93 | } 94 | } 95 | 96 | @end 97 | 98 | @implementation NSMenuDarkMaker 99 | 100 | - (id)initWithMenu:(NSMenu *)menu; 101 | { 102 | self = [super init]; 103 | if (self) 104 | { 105 | mMenu = menu; 106 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(beginTracking:) 107 | name:NSMenuDidBeginTrackingNotification object:mMenu]; 108 | } 109 | return self; 110 | } 111 | 112 | - (void)dealloc; 113 | { 114 | mMenu = nil; 115 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 116 | } 117 | 118 | - (void)beginTracking:(NSNotification *)note; 119 | { 120 | [mMenu makeDark]; 121 | } 122 | 123 | @end 124 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/VMMModals.h: -------------------------------------------------------------------------------- 1 | // 2 | // VMMModals.h 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 11/10/2017. 6 | // Copyright © 2017 VitorMM. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface VMMModals : NSObject 12 | 13 | +(NSWindow*)modalsWindow; 14 | 15 | +(void)nextModalShouldRunOnWindow:(NSWindow*)window; 16 | +(void)modalsShouldRunOnWindow:(NSWindow*)window whenCalledDuringBlock:(void (^) (void))block; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/VMMModals.m: -------------------------------------------------------------------------------- 1 | // 2 | // VMMModals.m 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 11/10/2017. 6 | // Copyright © 2017 VitorMM. All rights reserved. 7 | // 8 | 9 | #import "VMMModals.h" 10 | 11 | @implementation VMMModals 12 | 13 | static NSWindow* _alertsWindow; 14 | 15 | static NSWindow* _temporaryAlertsWindow; 16 | static int _temporaryCounter; 17 | 18 | +(NSWindow*)modalsWindow 19 | { 20 | if (_temporaryCounter > 0) 21 | { 22 | _temporaryCounter--; 23 | return _temporaryAlertsWindow; 24 | } 25 | 26 | return _alertsWindow; 27 | } 28 | 29 | +(void)nextModalShouldRunOnWindow:(NSWindow*)window 30 | { 31 | _temporaryCounter = 1; 32 | _temporaryAlertsWindow = window; 33 | } 34 | +(void)modalsShouldRunOnWindow:(NSWindow*)window whenCalledDuringBlock:(void (^) (void))block 35 | { 36 | _alertsWindow = window; 37 | block(); 38 | _alertsWindow = nil; 39 | } 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/VMMParentalControls.h: -------------------------------------------------------------------------------- 1 | // 2 | // VMMUserAuthorization.h 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 05/02/2018. 6 | // Copyright © 2018 VitorMM. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef enum VMMParentalControlsItunesGamesAgeRestriction 12 | { 13 | VMMParentalControlsItunesGamesAgeRestrictionNone = 1000, 14 | VMMParentalControlsItunesGamesAgeRestriction4 = 100, 15 | VMMParentalControlsItunesGamesAgeRestriction9 = 200, 16 | VMMParentalControlsItunesGamesAgeRestriction12 = 300, 17 | VMMParentalControlsItunesGamesAgeRestriction17 = 600, 18 | } VMMParentalControlsItunesGamesAgeRestriction; 19 | 20 | 21 | @interface VMMParentalControls : NSObject 22 | 23 | +(BOOL)isEnabled; 24 | 25 | +(id)parentalControlsValueForAppWithDomain:(NSString*)appDomain keyName:(NSString*)keyName; 26 | 27 | +(BOOL)iTunesMatureGamesAllowed; 28 | +(VMMParentalControlsItunesGamesAgeRestriction)iTunesAgeRestrictionForGames; 29 | 30 | +(BOOL)isAppRestrictionEnabled; 31 | +(BOOL)isAppUseRestricted:(NSString*)appPath; 32 | 33 | +(BOOL)isInternetUseRestricted; 34 | +(BOOL)isWebsiteAllowed:(NSString*)websiteAddress; 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/VMMParentalControls.m: -------------------------------------------------------------------------------- 1 | // 2 | // VMMUserAuthorization.m 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 05/02/2018. 6 | // Copyright © 2018 VitorMM. All rights reserved. 7 | // 8 | 9 | #import "VMMParentalControls.h" 10 | 11 | #import "VMMPropertyList.h" 12 | 13 | #import "NSBundle+Extension.h" 14 | #import "NSString+Extension.h" 15 | #import "NSTask+Extension.h" 16 | 17 | static NSString* _Nonnull const VMMParentalControlsAppDomainItunes = @"com.apple.iTunes"; 18 | static NSString* _Nonnull const VMMParentalControlsAppDomainApplicationAccess = @"com.apple.applicationaccess.new"; 19 | static NSString* _Nonnull const VMMParentalControlsAppDomainContentFilter = @"com.apple.familycontrols.contentfilter"; 20 | 21 | static NSString* _Nonnull const VMMParentalControlsItunesGamesAgeLimit = @"gamesLimit"; 22 | static NSString* _Nonnull const VMMParentalControlsApplicationAccessFamilyControlEnabled = @"familyControlsEnabled"; 23 | static NSString* _Nonnull const VMMParentalControlsApplicationAccessWhiteList = @"whiteList"; 24 | static NSString* _Nonnull const VMMParentalControlsContentFilterWhiteListEnabled = @"whitelistEnabled"; 25 | static NSString* _Nonnull const VMMParentalControlsContentFilterWhiteList = @"siteWhitelist"; 26 | static NSString* _Nonnull const VMMParentalControlsContentFilterBlackList = @"filterBlacklist"; 27 | 28 | static NSString* _Nonnull const VMMParentalControlsApplicationAccessWhiteListPath = @"path"; 29 | static NSString* _Nonnull const VMMParentalControlsContentFilterWhiteListAddress = @"address"; 30 | 31 | @implementation VMMParentalControls 32 | 33 | +(BOOL)isEnabled 34 | { 35 | @autoreleasepool 36 | { 37 | NSString* dsclOutputString = [NSTask runProgram:@"dscl" withFlags:@[@".", @"mcxexport", NSHomeDirectory()]]; 38 | if (dsclOutputString == nil || dsclOutputString.length == 0) return FALSE; 39 | } 40 | 41 | return TRUE; 42 | } 43 | 44 | +(id)parentalControlsValueForAppWithDomain:(NSString*)appDomain keyName:(NSString*)keyName 45 | { 46 | // Reference: 47 | // https://real-world-systems.com/docs/dslocal.db.html 48 | 49 | @autoreleasepool 50 | { 51 | NSString* dsclOutputString = [NSTask runProgram:@"dscl" withFlags:@[@".", @"mcxexport", NSHomeDirectory(), appDomain, keyName]]; 52 | if (dsclOutputString == nil || dsclOutputString.length == 0) return nil; 53 | 54 | NSDictionary* dsclOutput = [VMMPropertyList propertyListWithArchivedString:dsclOutputString]; 55 | if (dsclOutput == nil || [dsclOutput isKindOfClass:[NSDictionary class]] == FALSE) return nil; 56 | 57 | NSDictionary* dict = dsclOutput[appDomain][keyName]; 58 | if (dict == nil) return nil; 59 | 60 | return dict[@"value"]; 61 | } 62 | } 63 | 64 | +(BOOL)iTunesMatureGamesAllowed 65 | { 66 | VMMParentalControlsItunesGamesAgeRestriction value = [self iTunesAgeRestrictionForGames]; 67 | return value == VMMParentalControlsItunesGamesAgeRestrictionNone || 68 | value == VMMParentalControlsItunesGamesAgeRestriction17; 69 | } 70 | +(VMMParentalControlsItunesGamesAgeRestriction)iTunesAgeRestrictionForGames 71 | { 72 | NSNumber* valueNumber = [self parentalControlsValueForAppWithDomain:VMMParentalControlsAppDomainItunes 73 | keyName:VMMParentalControlsItunesGamesAgeLimit]; 74 | if (valueNumber == nil || [valueNumber isKindOfClass:[NSNumber class]] == FALSE) 75 | return VMMParentalControlsItunesGamesAgeRestrictionNone; 76 | 77 | NSInteger value = valueNumber.integerValue; 78 | if (value == 0) return VMMParentalControlsItunesGamesAgeRestrictionNone; 79 | 80 | return (VMMParentalControlsItunesGamesAgeRestriction)value; 81 | } 82 | 83 | +(BOOL)isAppRestrictionEnabled 84 | { 85 | NSNumber* valueNumber = [self parentalControlsValueForAppWithDomain:VMMParentalControlsAppDomainApplicationAccess 86 | keyName:VMMParentalControlsApplicationAccessFamilyControlEnabled]; 87 | if (valueNumber == nil || [valueNumber isKindOfClass:[NSNumber class]] == FALSE) return FALSE; 88 | 89 | return valueNumber.boolValue; 90 | } 91 | +(BOOL)isAppUseRestricted:(NSString*)appPath 92 | { 93 | if ([self isAppRestrictionEnabled] == FALSE) return FALSE; 94 | 95 | NSArray* appsList = [self parentalControlsValueForAppWithDomain:VMMParentalControlsAppDomainApplicationAccess 96 | keyName:VMMParentalControlsApplicationAccessWhiteList]; 97 | 98 | for (NSDictionary* itemApp in appsList) 99 | { 100 | NSString* itemAppPath = itemApp[VMMParentalControlsApplicationAccessWhiteListPath]; 101 | if ([itemAppPath isEqualToString:appPath]) return FALSE; 102 | } 103 | 104 | return TRUE; 105 | } 106 | 107 | +(BOOL)isInternetUseRestricted 108 | { 109 | NSNumber* whiteListEnabled = [self parentalControlsValueForAppWithDomain:VMMParentalControlsAppDomainContentFilter 110 | keyName:VMMParentalControlsContentFilterWhiteListEnabled]; 111 | if (whiteListEnabled == nil || [whiteListEnabled isKindOfClass:[NSNumber class]] == FALSE) return FALSE; 112 | 113 | return whiteListEnabled.boolValue; 114 | } 115 | +(BOOL)isWebsiteAllowed:(NSString*)websiteAddress 116 | { 117 | if ([self isInternetUseRestricted] == FALSE) return TRUE; 118 | 119 | NSArray* whiteList = [self parentalControlsValueForAppWithDomain:VMMParentalControlsAppDomainContentFilter 120 | keyName:VMMParentalControlsContentFilterWhiteList]; 121 | if (whiteList == nil || [whiteList isKindOfClass:[NSArray class]] == FALSE) return TRUE; 122 | 123 | NSArray* blackList = [self parentalControlsValueForAppWithDomain:VMMParentalControlsAppDomainContentFilter 124 | keyName:VMMParentalControlsContentFilterBlackList]; 125 | if (blackList == nil || [blackList isKindOfClass:[NSArray class]] == FALSE) return TRUE; 126 | 127 | for (NSString* blackListItemAddress in blackList) 128 | { 129 | if ([websiteAddress hasPrefix:blackListItemAddress]) 130 | { 131 | return FALSE; 132 | } 133 | } 134 | 135 | for (NSDictionary* whiteListItem in whiteList) 136 | { 137 | NSString* whiteListItemAddress = whiteListItem[VMMParentalControlsContentFilterWhiteListAddress]; 138 | if (whiteListItemAddress != nil && [websiteAddress hasPrefix:whiteListItemAddress]) 139 | { 140 | return TRUE; 141 | } 142 | } 143 | 144 | return FALSE; 145 | } 146 | 147 | @end 148 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/VMMPropertyList.h: -------------------------------------------------------------------------------- 1 | // 2 | // VMMPropertyList.h 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 08/03/2018. 6 | // Copyright © 2018 VitorMM. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface VMMPropertyList : NSObject 12 | 13 | +(nullable id)propertyListWithUnarchivedString:(nonnull NSString*)string; 14 | +(nullable id)propertyListWithUnarchivedData:(nonnull NSData*)data; 15 | 16 | +(nullable id)propertyListWithArchivedString:(nonnull NSString *)string; 17 | +(nullable id)propertyListWithArchivedData:(nonnull NSData *)data; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/VMMPropertyList.m: -------------------------------------------------------------------------------- 1 | // 2 | // VMMPropertyList.m 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 08/03/2018. 6 | // Copyright © 2018 VitorMM. All rights reserved. 7 | // 8 | 9 | #import "VMMPropertyList.h" 10 | 11 | @implementation VMMPropertyList 12 | 13 | +(nullable id)propertyListWithUnarchivedString:(nonnull NSString*)string 14 | { 15 | id result; 16 | 17 | @autoreleasepool 18 | { 19 | NSData* data = [string dataUsingEncoding:NSUTF8StringEncoding]; 20 | result = [self propertyListWithUnarchivedData:data]; 21 | } 22 | 23 | return result; 24 | 25 | } 26 | +(nullable id)propertyListWithUnarchivedData:(nonnull NSData*)data 27 | { 28 | id propertyList; 29 | 30 | @autoreleasepool 31 | { 32 | NSError *error; 33 | NSPropertyListFormat format; 34 | propertyList = [NSPropertyListSerialization propertyListWithData:data options:NSPropertyListImmutable 35 | format:&format error:&error]; 36 | if (propertyList == nil || error != nil) 37 | { 38 | return nil; 39 | } 40 | } 41 | 42 | return propertyList; 43 | } 44 | 45 | +(nullable id)propertyListWithArchivedString:(nonnull NSString *)string 46 | { 47 | id result; 48 | 49 | @autoreleasepool 50 | { 51 | NSData* data = [string dataUsingEncoding:NSUTF8StringEncoding]; 52 | result = [self propertyListWithArchivedData:data]; 53 | } 54 | 55 | return result; 56 | } 57 | +(nullable id)propertyListWithArchivedData:(nonnull NSData *)data 58 | { 59 | @try 60 | { 61 | return [NSKeyedUnarchiver unarchiveObjectWithData:data]; 62 | } 63 | @catch (NSException* exception) 64 | { 65 | return nil; 66 | } 67 | } 68 | 69 | @end 70 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/VMMTextFileView.h: -------------------------------------------------------------------------------- 1 | // 2 | // VMMTextFileView.h 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 21/11/2017. 6 | // Copyright © 2017 VitorMM. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface VMMTextFileView : NSTextView 12 | { 13 | NSTimer *monitorTimer; 14 | 15 | NSString* _textFilePath; 16 | NSStringEncoding _textFileEncoding; 17 | } 18 | 19 | @property (nonatomic, nullable) NSRunLoopMode runLoopMode; 20 | 21 | -(NSString* _Nullable)textFileContents; 22 | -(void)showTextFileAtPath:(nonnull NSString*)filePath withEncoding:(NSStringEncoding)encoding refreshingWithTimeInterval:(NSTimeInterval)interval; 23 | -(void)stopRefreshing; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/VMMTextFileView.m: -------------------------------------------------------------------------------- 1 | // 2 | // VMMTextFileView.m 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 21/11/2017. 6 | // Copyright © 2017 VitorMM. All rights reserved. 7 | // 8 | 9 | #import "VMMTextFileView.h" 10 | 11 | #import "NSString+Extension.h" 12 | #import "NSText+Extension.h" 13 | #import "NSTimer+Extension.h" 14 | 15 | @implementation VMMTextFileView 16 | 17 | -(void)awakeFromNib 18 | { 19 | _runLoopMode = NSDefaultRunLoopMode; 20 | } 21 | 22 | -(NSString* _Nullable)textFileContents 23 | { 24 | if (_textFileEncoding == -1) 25 | { 26 | return [NSString stringWithContentsOfFile:_textFilePath]; 27 | } 28 | 29 | return [NSString stringWithContentsOfFile:_textFilePath encoding:_textFileEncoding]; 30 | } 31 | -(void)reloadTextFileForTimer:(NSTimer*)timer 32 | { 33 | NSString* wineLog = [self textFileContents]; 34 | NSRange priorSelectedRange = wineLog.length >= self.string.length ? self.selectedRange : NSMakeRange(0, 0); 35 | [self deselectText]; 36 | 37 | if (wineLog != nil) 38 | { 39 | @try 40 | { 41 | [self setString:wineLog]; 42 | [self setSelectedRange:priorSelectedRange]; 43 | } 44 | @catch (NSException* exception) 45 | { 46 | [self setString:@""]; 47 | [self setSelectedRange:NSMakeRange(0, 0)]; 48 | } 49 | } 50 | 51 | [self scrollToBottom]; 52 | } 53 | -(void)startReloadingTextFileWithTimeInterval:(NSTimeInterval)interval 54 | { 55 | [self setSelectedRangeAsTheBeginOfTheField]; 56 | [self setString:@""]; 57 | 58 | monitorTimer = [NSTimer scheduledTimerWithRunLoopMode:_runLoopMode timeInterval:interval target:self 59 | selector:@selector(reloadTextFileForTimer:) userInfo:nil]; 60 | } 61 | -(void)showTextFileAtPath:(nonnull NSString*)filePath withEncoding:(NSStringEncoding)encoding refreshingWithTimeInterval:(NSTimeInterval)interval 62 | { 63 | _textFilePath = filePath; 64 | _textFileEncoding = encoding; 65 | 66 | if (interval == 0) 67 | { 68 | [self reloadTextFileForTimer:nil]; 69 | } 70 | else 71 | { 72 | [self startReloadingTextFileWithTimeInterval:interval]; 73 | } 74 | } 75 | -(void)stopRefreshing 76 | { 77 | if (monitorTimer == nil) return; 78 | 79 | [monitorTimer invalidate]; 80 | [self reloadTextFileForTimer:nil]; 81 | } 82 | 83 | @end 84 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/VMMUUID.h: -------------------------------------------------------------------------------- 1 | // 2 | // VMMUUID.h 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 03/11/2017. 6 | // Copyright © 2017 VitorMM. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NSString* _Nonnull VMMUUIDCreate(void); 12 | 13 | @interface VMMUUID : NSObject 14 | 15 | +(nonnull NSString*)newUUIDString; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/VMMUUID.m: -------------------------------------------------------------------------------- 1 | // 2 | // VMMUUID.m 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 03/11/2017. 6 | // Copyright © 2017 VitorMM. All rights reserved. 7 | // 8 | 9 | #import "VMMUUID.h" 10 | 11 | #import "VMMComputerInformation.h" 12 | 13 | NSString* _Nonnull VMMUUIDCreate(void) 14 | { 15 | return [VMMUUID newUUIDString]; 16 | } 17 | 18 | @implementation VMMUUID 19 | 20 | +(nonnull NSString*)newUUIDString 21 | { 22 | @autoreleasepool 23 | { 24 | if (IsClassNSUUIDAvailable == false) 25 | { 26 | @autoreleasepool 27 | { 28 | CFUUIDRef udid = CFUUIDCreate(NULL); 29 | NSString* newUUID = (NSString *) CFBridgingRelease(CFUUIDCreateString(NULL, udid)); 30 | CFRelease(udid); 31 | return newUUID; 32 | } 33 | } 34 | 35 | return [[NSUUID UUID] UUIDString]; 36 | } 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/VMMUserNotificationCenter.h: -------------------------------------------------------------------------------- 1 | // 2 | // VMMUserNotificationCenter.h 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 22/02/17. 6 | // Copyright © 2017 Vitor Marques de Miranda. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef enum { 12 | VMMUserNotificationNormal = 0, 13 | VMMUserNotificationOnlyWithAction = 1 << 0, 14 | VMMUserNotificationPreferGrowl = 1 << 1, 15 | VMMUserNotificationNoAlert = 1 << 2 16 | 17 | } VMMUserNotificationCenterOptions; 18 | 19 | @protocol VMMUserNotificationCenterDelegate 20 | -(void)actionButtonPressedForNotificationWithUserInfo:(nullable NSObject*)userInfo; 21 | @end 22 | 23 | @interface VMMUserNotificationCenter : NSObject 24 | 25 | @property (nonatomic, nullable) id delegate; 26 | 27 | +(nonnull instancetype)defaultUserNotificationCenter; 28 | 29 | +(BOOL)isGrowlAvailable; 30 | +(BOOL)isNSUserNotificationCenterAvailable; 31 | 32 | -(BOOL)deliverNotificationWithTitle:(nullable NSString*)title message:(nullable NSString*)message userInfo:(nullable NSObject*)info icon:(nullable NSImage*)icon actionButtonText:(nullable NSString*)actionButton options:(VMMUserNotificationCenterOptions)options; 33 | 34 | -(BOOL)deliverNotificationWithTitle:(nullable NSString*)title message:(nullable NSString*)message icon:(nullable NSImage*)icon options:(VMMUserNotificationCenterOptions)options; 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/VMMVersion.h: -------------------------------------------------------------------------------- 1 | // 2 | // VMMVersion.h 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 18/09/17. 6 | // Copyright © 2017 Vitor Marques de Miranda. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef enum VMMVersionCompare 12 | { 13 | VMMVersionCompareFirstIsNewest, 14 | VMMVersionCompareSecondIsNewest, 15 | VMMVersionCompareSame 16 | } VMMVersionCompare; 17 | 18 | @interface VMMVersion : NSObject 19 | 20 | @property (nonatomic, strong) NSArray* _Nonnull components; 21 | 22 | -(nonnull instancetype)initWithString:(nonnull NSString*)string; 23 | -(VMMVersionCompare)compareWithVersion:(nonnull VMMVersion*)version; 24 | 25 | +(VMMVersionCompare)compareVersionString:(nonnull NSString*)PK1 withVersionString:(nonnull NSString*)PK2; 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/VMMVersion.m: -------------------------------------------------------------------------------- 1 | // 2 | // VMMVersion.m 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 18/09/17. 6 | // Copyright © 2017 Vitor Marques de Miranda. All rights reserved. 7 | // 8 | 9 | #import "VMMVersion.h" 10 | 11 | #import "NSString+Extension.h" 12 | 13 | @implementation VMMVersion 14 | 15 | -(nonnull instancetype)initWithString:(nonnull NSString*)string 16 | { 17 | self = [super init]; 18 | if (self) 19 | { 20 | self.components = [string componentsSeparatedByString:@"."]; 21 | } 22 | return self; 23 | } 24 | -(VMMVersionCompare)compareWithVersion:(nonnull VMMVersion*)version 25 | { 26 | @autoreleasepool 27 | { 28 | NSArray* PKArray1 = self.components; 29 | NSArray* PKArray2 = version.components; 30 | 31 | for (int x = 0; x < PKArray1.count && x < PKArray2.count; x++) 32 | { 33 | if ([PKArray1[x] initialIntegerValue].intValue < [PKArray2[x] initialIntegerValue].intValue) 34 | return VMMVersionCompareSecondIsNewest; 35 | 36 | if ([PKArray1[x] initialIntegerValue].intValue > [PKArray2[x] initialIntegerValue].intValue) 37 | return VMMVersionCompareFirstIsNewest; 38 | 39 | if (PKArray1[x].length > PKArray2[x].length) return VMMVersionCompareFirstIsNewest; 40 | if (PKArray1[x].length < PKArray2[x].length) return VMMVersionCompareSecondIsNewest; 41 | } 42 | 43 | if (PKArray1.count < PKArray2.count) return VMMVersionCompareSecondIsNewest; 44 | if (PKArray1.count > PKArray2.count) return VMMVersionCompareFirstIsNewest; 45 | 46 | return VMMVersionCompareSame; 47 | } 48 | } 49 | 50 | +(VMMVersionCompare)compareVersionString:(nonnull NSString*)PK1 withVersionString:(nonnull NSString*)PK2 51 | { 52 | @autoreleasepool 53 | { 54 | VMMVersion* version1 = [[VMMVersion alloc] initWithString:PK1]; 55 | VMMVersion* version2 = [[VMMVersion alloc] initWithString:PK2]; 56 | 57 | return [version1 compareWithVersion:version2]; 58 | } 59 | } 60 | 61 | @end 62 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/VMMVideoCard.h: -------------------------------------------------------------------------------- 1 | // 2 | // VMMVideoCard.h 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 18/03/18. 6 | // Copyright © 2018 VitorMM. All rights reserved. 7 | // 8 | // References: 9 | // https://lists.denx.de/pipermail/u-boot/2015-May/215147.html 10 | // 11 | 12 | #import 13 | #import "VMMComputerInformation.h" 14 | 15 | static NSString * _Nonnull const VMMVideoCardModelNameKey = @"sppci_model"; 16 | static NSString * _Nonnull const VMMVideoCardChipsetNameKey = @"_name"; 17 | static NSString * _Nonnull const VMMVideoCardDeviceTypeKey = @"sppci_device_type"; // eg. 'GPU' 18 | static NSString * _Nonnull const VMMVideoCardBusKey = @"sppci_bus"; // eg. VMMVideoCardBusPCIe 19 | static NSString * _Nonnull const VMMVideoCardMemorySizeBuiltInAlternateKey = @"_spdisplays_vram"; // eg. '1536 MB' 20 | static NSString * _Nonnull const VMMVideoCardMemorySizeBuiltInKey = @"spdisplays_vram_shared"; // eg. '1536 MB' 21 | static NSString * _Nonnull const VMMVideoCardMemorySizePciOrPcieKey = @"spdisplays_vram"; // eg. '1536 MB' 22 | static NSString * _Nonnull const VMMVideoCardVendorIDKey = @"spdisplays_vendor-id"; // eg. '0x8086' 23 | static NSString * _Nonnull const VMMVideoCardVendorKey = @"spdisplays_vendor"; 24 | static NSString * _Nonnull const VMMVideoCardDeviceIDKey = @"spdisplays_device-id"; // eg. '0x0046' 25 | static NSString * _Nonnull const VMMVideoCardMetalSupportKey = @"spdisplays_metal"; 26 | static NSString * _Nonnull const VMMVideoCardKextInfoKey = @"sppci_kextinfo"; // eg. 'sppci_kextnotloaded' 27 | 28 | static NSString * _Nonnull const VMMVideoCardKextInfoNotLoaded = @"sppci_kextnotloaded"; 29 | 30 | static NSString * _Nonnull const VMMVideoCardTypeApple = @"Apple Silicon"; 31 | static NSString * _Nonnull const VMMVideoCardTypeIntelHD = @"Intel HD"; 32 | static NSString * _Nonnull const VMMVideoCardTypeIntelUHD = @"Intel UHD"; 33 | static NSString * _Nonnull const VMMVideoCardTypeIntelIris = @"Intel Iris"; 34 | static NSString * _Nonnull const VMMVideoCardTypeIntelIrisPro = @"Intel Iris Pro"; 35 | static NSString * _Nonnull const VMMVideoCardTypeIntelIrisPlus = @"Intel Iris Plus"; 36 | static NSString * _Nonnull const VMMVideoCardTypeIntelGMA = @"Intel GMA"; 37 | static NSString * _Nonnull const VMMVideoCardTypeIntelCoffeeLake = @"Intel Coffee Lake"; 38 | static NSString * _Nonnull const VMMVideoCardTypeATIAMD = @"ATI/AMD"; 39 | static NSString * _Nonnull const VMMVideoCardTypeNVIDIA = @"NVIDIA"; 40 | 41 | static NSString * _Nonnull const VMMVideoCardDeviceTypeGPU = @"spdisplays_gpu"; 42 | static NSString * _Nonnull const VMMVideoCardDeviceTypeeGPU = @"spdisplays_egpu"; 43 | 44 | static NSString * _Nonnull const VMMVideoCardBusPCIe = @"spdisplays_pcie_device"; 45 | static NSString * _Nonnull const VMMVideoCardBusPCI = @"sppci_pci_device"; 46 | static NSString * _Nonnull const VMMVideoCardBusBuiltIn = @"spdisplays_builtin"; 47 | 48 | static NSString * _Nonnull const VMMVideoCardVendorIDApple = @"0x05ac"; 49 | static NSString * _Nonnull const VMMVideoCardVendorIDIntel = @"0x8086"; 50 | static NSString * _Nonnull const VMMVideoCardVendorIDNVIDIA = @"0x10de"; 51 | static NSString * _Nonnull const VMMVideoCardVendorIDATIAMD = @"0x1002"; 52 | 53 | static NSString * _Nonnull const VMMVideoCardVendorApple = @"Apple"; 54 | static NSString * _Nonnull const VMMVideoCardVendorIntel = @"Intel"; 55 | static NSString * _Nonnull const VMMVideoCardVendorNVIDIA = @"NVIDIA"; 56 | static NSString * _Nonnull const VMMVideoCardVendorATIAMD = @"ATI/AMD"; 57 | 58 | static NSString * _Nonnull const VMMVideoCardNameVirtualBox = @"VirtualBox VM"; 59 | static NSString * _Nonnull const VMMVideoCardTypeVirtualBox = @"VirtualBox"; 60 | static NSString * _Nonnull const VMMVideoCardVendorVirtualBox = @"VirtualBox"; 61 | static NSString * _Nonnull const VMMVideoCardVendorIDVirtualBox = @"0x80ee"; 62 | static NSString * _Nonnull const VMMVideoCardDeviceIDVirtualBox = @"0xbeef"; 63 | 64 | static NSString * _Nonnull const VMMVideoCardNameVMware = @"VMware VM"; 65 | static NSString * _Nonnull const VMMVideoCardTypeVMware = @"VMware"; 66 | static NSString * _Nonnull const VMMVideoCardVendorVMware = @"VMware"; 67 | static NSString * _Nonnull const VMMVideoCardVendorIDVMware = @"0x15ad"; 68 | 69 | static NSString * _Nonnull const VMMVideoCardNameParallelsDesktop = @"Parallels Desktop VM"; 70 | static NSString * _Nonnull const VMMVideoCardTypeParallelsDesktop = @"Parallels Desktop"; 71 | static NSString * _Nonnull const VMMVideoCardVendorParallelsDesktop = @"Parallels Desktop"; 72 | static NSString * _Nonnull const VMMVideoCardVendorIDParallelsDesktop = @"0x1ab8"; 73 | 74 | static NSString * _Nonnull const VMMVideoCardNameMicrosoftRemoteDesktop = @"Microsoft Remote Desktop"; 75 | static NSString * _Nonnull const VMMVideoCardTypeMicrosoftRemoteDesktop = @"Microsoft Remote Desktop"; 76 | static NSString * _Nonnull const VMMVideoCardVendorMicrosoftRemoteDesktop = @"Microsoft Remote Desktop"; 77 | static NSString * _Nonnull const VMMVideoCardVendorIDMicrosoftRemoteDesktop = @"0xbaad"; 78 | 79 | static NSString * _Nonnull const VMMVideoCardNameQemu = @"QEMU Emulated Graphic Card"; 80 | static NSString * _Nonnull const VMMVideoCardTypeQemu = @"QEMU"; 81 | static NSString * _Nonnull const VMMVideoCardVendorQemu = @"QEMU"; 82 | static NSString * _Nonnull const VMMVideoCardVendorIDQemu = @"0x1234"; 83 | static NSString * _Nonnull const VMMVideoCardDeviceIDQemu = @"0x1111"; 84 | 85 | 86 | static NSString * _Nonnull const VMMVideoCardDeviceIDIntelHDGraphics = @"0x0046"; 87 | static NSString * _Nonnull const VMMVideoCardDeviceIDIntelHDGraphics3000 = @"0x0116"; 88 | static NSString * _Nonnull const VMMVideoCardDeviceIDIntelHDGraphics4000 = @"0x0166"; 89 | static NSString * _Nonnull const VMMVideoCardDeviceIDNVIDIAGeForce9400M = @"0x0863"; 90 | 91 | static NSString * _Nonnull const VMMVideoCardDeviceIDNVIDIAGeForce320M_1 = @"0x08a0"; 92 | static NSString * _Nonnull const VMMVideoCardDeviceIDNVIDIAGeForce320M_2 = @"0x08a2"; 93 | static NSString * _Nonnull const VMMVideoCardDeviceIDNVIDIAGeForce320M_3 = @"0x08a3"; 94 | static NSString * _Nonnull const VMMVideoCardDeviceIDNVIDIAGeForce320M_4 = @"0x08a4"; 95 | static NSString * _Nonnull const VMMVideoCardDeviceIDNVIDIAGeForce320M_5 = @"0x08a5"; 96 | 97 | static NSInteger const VMMVideoCardMemoryMinimumSize = 64; 98 | 99 | static NSString * _Nonnull const VMMVideoCardTemporaryKeyIOServiceValues = @"RawRegIOServiceValues"; 100 | static NSString * _Nonnull const VMMVideoCardTemporaryKeyOpenGlApiMemorySizes = @"temp_memory_size_opengl_api_values"; 101 | 102 | @interface VMMVideoCard : NSObject 103 | { 104 | NSLock* _Nullable nameLock; 105 | NSLock* _Nullable typeLock; 106 | NSLock* _Nullable busLock; 107 | NSLock* _Nullable deviceIDLock; 108 | NSLock* _Nullable vendorIDLock; 109 | NSLock* _Nullable vendorLock; 110 | NSLock* _Nullable memorySizeInMegabytesLock; 111 | } 112 | 113 | -(instancetype _Nullable )initVideoCardWithDictionary:(NSDictionary* _Nonnull)dict; 114 | 115 | @property (nonatomic, strong, readonly) NSDictionary* _Nonnull dictionary; 116 | 117 | @property (nonatomic, strong, readonly) NSString* _Nullable modelName; 118 | @property (nonatomic, strong, readonly) NSString* _Nullable chipsetName; 119 | @property (nonatomic, strong, readonly) NSString* _Nullable type; 120 | @property (nonatomic, strong, readonly) NSString* _Nullable bus; 121 | @property (nonatomic, strong, readonly) NSString* _Nullable deviceID; 122 | @property (nonatomic, strong, readonly) NSString* _Nullable vendorID; 123 | @property (nonatomic, strong, readonly) NSString* _Nullable vendor; 124 | @property (nonatomic, strong, readonly) NSNumber* _Nullable memorySizeInMegabytes; 125 | 126 | -(BOOL)kextLoaded; 127 | 128 | -(BOOL)isExternalGpu; 129 | 130 | -(BOOL)supportsMetal; 131 | -(VMMMetalFeatureSet)metalFeatureSet; 132 | 133 | -(NSString* _Nonnull)descriptiveName; 134 | -(NSString* _Nonnull)veryDescriptiveName; 135 | 136 | -(BOOL)hasRealVendorID; 137 | -(BOOL)isComplete; 138 | -(BOOL)isVirtualMachineVideoCard; 139 | 140 | -(BOOL)isSameVideoCard:(nonnull VMMVideoCard*)vc; 141 | -(void)mergeWithIOPCIVideoCard:(nonnull VMMVideoCard*)vc; 142 | 143 | @end 144 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/VMMVideoCardManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // VMMVideoCardManager.h 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 04/10/18. 6 | // Copyright © 2018 VitorMM. All rights reserved. 7 | // 8 | 9 | #ifndef VMMVideoCardManager_Class 10 | #define VMMVideoCardManager_Class 11 | 12 | #import 13 | #import "VMMVideoCard.h" 14 | 15 | @interface VMMVideoCardManager : NSObject 16 | 17 | /*! 18 | * @discussion Returns every available information about every available video card. 19 | * @return A VMMVideoCard array with information related with every available video card. 20 | */ 21 | +(NSArray* _Nonnull)videoCards; 22 | 23 | +(NSArray* _Nonnull)videoCardsWithKext; 24 | 25 | /*! 26 | * @discussion Returns every available information about the main video card. 27 | * @return A VMMVideoCard with information related with the main video card. 28 | */ 29 | +(VMMVideoCard* _Nullable)bestVideoCard; 30 | +(VMMVideoCard* _Nullable)bestInternalVideoCard; 31 | +(VMMVideoCard* _Nullable)bestExternalVideoCard; 32 | 33 | @end 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/VMMView.h: -------------------------------------------------------------------------------- 1 | // 2 | // VMMView.h 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 07/11/2017. 6 | // Copyright © 2017 VitorMM. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface VMMView : NSView 12 | 13 | typedef NS_ENUM(NSUInteger, VMMViewBorderSide) 14 | { 15 | VMMViewBorderSideLeft = 1, 16 | VMMViewBorderSideRight = 2, 17 | VMMViewBorderSideTop = 4, 18 | VMMViewBorderSideBottom = 8 19 | }; 20 | 21 | @property (nonatomic, strong) NSColor* borderColor; 22 | @property (nonatomic, strong) NSNumber* borderThickness; 23 | @property (nonatomic, strong) NSNumber* borderSides; 24 | 25 | @property (nonatomic, strong) NSColor* backgroundColor; 26 | @property (nonatomic, strong) NSImage* backgroundImage; 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/VMMView.m: -------------------------------------------------------------------------------- 1 | // 2 | // VMMView.m 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 07/11/2017. 6 | // Copyright © 2017 VitorMM. All rights reserved. 7 | // 8 | 9 | #import "VMMView.h" 10 | 11 | @implementation VMMView 12 | 13 | -(void)setBackgroundColor:(NSColor*)color 14 | { 15 | _backgroundColor = color; 16 | [self setNeedsDisplay:YES]; 17 | } 18 | -(void)setBackgroundImage:(NSImage *)backgroundImage 19 | { 20 | _backgroundImage = backgroundImage; 21 | [self setNeedsDisplay:YES]; 22 | } 23 | 24 | -(void)drawRect:(NSRect)dirtyRect 25 | { 26 | CGFloat borderThickness = 0; 27 | if (_borderColor) 28 | { 29 | borderThickness = _borderThickness.doubleValue; 30 | 31 | [_borderColor setFill]; 32 | NSRectFillUsingOperation(dirtyRect, NSCompositeSourceOver); 33 | } 34 | 35 | if (_backgroundColor) 36 | { 37 | [_backgroundColor setFill]; 38 | 39 | BOOL hasLeftMargin = (_borderSides == nil || (_borderSides.unsignedIntegerValue & VMMViewBorderSideLeft) != 0); 40 | BOOL hasRightMargin = (_borderSides == nil || (_borderSides.unsignedIntegerValue & VMMViewBorderSideRight) != 0); 41 | BOOL hasTopMargin = (_borderSides == nil || (_borderSides.unsignedIntegerValue & VMMViewBorderSideTop) != 0); 42 | BOOL hasBottomMargin = (_borderSides == nil || (_borderSides.unsignedIntegerValue & VMMViewBorderSideBottom) != 0); 43 | 44 | CGFloat leftMargin = hasLeftMargin ? borderThickness : 0; 45 | CGFloat rightMargin = hasRightMargin ? borderThickness : 0; 46 | CGFloat topMargin = hasTopMargin ? borderThickness : 0; 47 | CGFloat bottomMargin = hasBottomMargin ? borderThickness : 0; 48 | 49 | NSRect bgRect = NSMakeRect(dirtyRect.origin.x + leftMargin, dirtyRect.origin.y + bottomMargin, 50 | dirtyRect.size.width - (leftMargin + rightMargin), 51 | dirtyRect.size.height - (topMargin + bottomMargin)); 52 | NSRectFillUsingOperation(bgRect, NSCompositeSourceOver); 53 | } 54 | 55 | [super drawRect:dirtyRect]; 56 | 57 | if (_backgroundImage) 58 | { 59 | [_backgroundImage setSize:self.frame.size]; 60 | [_backgroundImage drawAtPoint:NSZeroPoint fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1]; 61 | } 62 | } 63 | 64 | @end 65 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/VMMVirtualKeycode.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Summary: 3 | * Virtual keycodes 4 | * 5 | * Discussion: 6 | * These constants are the virtual keycodes defined originally in 7 | * Inside Mac Volume V, pg. V-191. They identify physical keys on a 8 | * keyboard. Those constants with "ANSI" in the name are labeled 9 | * according to the key position on an ANSI-standard US keyboard. 10 | * For example, kVK_ANSI_A indicates the virtual keycode for the key 11 | * with the letter 'A' in the US keyboard layout. Other keyboard 12 | * layouts may have the 'A' key label on a different physical key; 13 | * in this case, pressing 'A' will generate a different virtual 14 | * keycode. 15 | */ 16 | // http://stackoverflow.com/a/16125341/4370893 17 | // 18 | // Power Mac Keypad Enter / iBook Enter Key (0x34): 19 | // https://bugs.chromium.org/p/chromium/issues/detail?id=542634 20 | // https://www.virtualbox.org/svn/vbox/trunk/src/VBox/Frontends/VirtualBox/src/platform/darwin/DarwinKeyboard.cpp 21 | // 22 | // Many keys that weren't in the first references: 23 | // http://www.insanelymac.com/forum/topic/236835-updated-2012-genericbrightnesskext/page-16 24 | // 25 | // Context Menu Key (0x6E): 26 | // https://chromium.googlesource.com/chromium/src/+/lkgr/ui/events/keycodes/keyboard_code_conversion_mac.mm 27 | // 28 | // Spotlight (0x81), Dashboard (0x82), Launchpad (0x83): 29 | // https://github.com/RehabMan/OS-X-Voodoo-PS2-Controller/blob/master/VoodooPS2Keyboard/VoodooPS2Keyboard.cpp 30 | // 31 | // Tilde (0x0A): 32 | // https://github.com/SFML/SFML/blob/master/src/SFML/Window/OSX/HIDInputManager.mm 33 | 34 | #import 35 | 36 | @interface VMMVirtualKeycode : NSObject 37 | 38 | +(nonnull NSArray*)allKeyNames; 39 | 40 | +(nonnull NSDictionary*)virtualKeycodeNames; 41 | +(nullable NSString*)nameOfVirtualKeycode:(CGKeyCode)key; 42 | 43 | @end 44 | 45 | enum { 46 | kVK_ANSI_A = 0x00, 47 | kVK_ANSI_S = 0x01, 48 | kVK_ANSI_D = 0x02, 49 | kVK_ANSI_F = 0x03, 50 | kVK_ANSI_H = 0x04, 51 | kVK_ANSI_G = 0x05, 52 | kVK_ANSI_Z = 0x06, 53 | kVK_ANSI_X = 0x07, 54 | kVK_ANSI_C = 0x08, 55 | kVK_ANSI_V = 0x09, 56 | kVK_ISO_Section = 0x0A, // Not present in keycode usage? Possibly Tilde; have to test 57 | kVK_ANSI_B = 0x0B, 58 | kVK_ANSI_Q = 0x0C, 59 | kVK_ANSI_W = 0x0D, 60 | kVK_ANSI_E = 0x0E, 61 | kVK_ANSI_R = 0x0F, 62 | kVK_ANSI_Y = 0x10, 63 | kVK_ANSI_T = 0x11, 64 | kVK_ANSI_1 = 0x12, 65 | kVK_ANSI_2 = 0x13, 66 | kVK_ANSI_3 = 0x14, 67 | kVK_ANSI_4 = 0x15, 68 | kVK_ANSI_6 = 0x16, 69 | kVK_ANSI_5 = 0x17, 70 | kVK_ANSI_Equal = 0x18, 71 | kVK_ANSI_9 = 0x19, 72 | kVK_ANSI_7 = 0x1A, 73 | kVK_ANSI_Minus = 0x1B, 74 | kVK_ANSI_8 = 0x1C, 75 | kVK_ANSI_0 = 0x1D, 76 | kVK_ANSI_RightBracket = 0x1E, 77 | kVK_ANSI_O = 0x1F, 78 | kVK_ANSI_U = 0x20, 79 | kVK_ANSI_LeftBracket = 0x21, 80 | kVK_ANSI_I = 0x22, 81 | kVK_ANSI_P = 0x23, 82 | kVK_Enter = 0x24, /* Mac calls it Return */ 83 | kVK_ANSI_L = 0x25, 84 | kVK_ANSI_J = 0x26, 85 | kVK_ANSI_Quote = 0x27, 86 | kVK_ANSI_K = 0x28, 87 | kVK_ANSI_Semicolon = 0x29, 88 | kVK_ANSI_Backslash = 0x2A, 89 | kVK_ANSI_Comma = 0x2B, 90 | kVK_ANSI_Slash = 0x2C, 91 | kVK_ANSI_N = 0x2D, 92 | kVK_ANSI_M = 0x2E, 93 | kVK_ANSI_Period = 0x2F, 94 | kVK_Tab = 0x30, 95 | kVK_Space = 0x31, 96 | kVK_ANSI_Grave = 0x32, 97 | kVK_Delete = 0x33, /* Backspace in Windows keyboards */ 98 | kVK_Play = 0x34, // Not present in keycode usage? 99 | kVK_Escape = 0x35, 100 | kVK_RightCommand = 0x36, 101 | kVK_LeftCommand = 0x37, 102 | kVK_LeftShift = 0x38, 103 | kVK_CapsLock = 0x39, 104 | kVK_LeftOption = 0x3A, 105 | kVK_LeftControl = 0x3B, 106 | kVK_RightShift = 0x3C, 107 | kVK_RightOption = 0x3D, 108 | kVK_RightControl = 0x3E, 109 | kVK_Function = 0x3F, // Not present in keycode usage? 110 | kVK_F17 = 0x40, 111 | kVK_ANSI_KeypadDecimal = 0x41, 112 | kVK_Next = 0x42, // Not present in keycode usage? 113 | kVK_ANSI_KeypadMultiply = 0x43, 114 | // 44? 115 | kVK_ANSI_KeypadPlus = 0x45, 116 | // 46? 117 | kVK_ANSI_KeypadClear = 0x47, /* This is also Num Lock */ 118 | kVK_VolumeUp = 0x48, 119 | kVK_VolumeDown = 0x49, 120 | kVK_Mute = 0x4A, 121 | kVK_ANSI_KeypadDivide = 0x4B, 122 | kVK_ANSI_KeypadEnter = 0x4C, 123 | kVK_Previous = 0x4D, // Not present in keycode usage? 124 | kVK_ANSI_KeypadMinus = 0x4E, 125 | kVK_F18 = 0x4F, 126 | kVK_F19 = 0x50, 127 | kVK_ANSI_KeypadEquals = 0x51, 128 | kVK_ANSI_Keypad0 = 0x52, 129 | kVK_ANSI_Keypad1 = 0x53, 130 | kVK_ANSI_Keypad2 = 0x54, 131 | kVK_ANSI_Keypad3 = 0x55, 132 | kVK_ANSI_Keypad4 = 0x56, 133 | kVK_ANSI_Keypad5 = 0x57, 134 | kVK_ANSI_Keypad6 = 0x58, 135 | kVK_ANSI_Keypad7 = 0x59, 136 | kVK_F20 = 0x5A, 137 | kVK_ANSI_Keypad8 = 0x5B, 138 | kVK_ANSI_Keypad9 = 0x5C, 139 | kVK_JIS_Yen = 0x5D, 140 | kVK_JIS_Underscore = 0x5E, // Not present in keycode usage? 141 | kVK_JIS_KeypadComma = 0x5F, 142 | kVK_F5 = 0x60, 143 | kVK_F6 = 0x61, 144 | kVK_F7 = 0x62, 145 | kVK_F3 = 0x63, 146 | kVK_F8 = 0x64, 147 | kVK_F9 = 0x65, 148 | kVK_JIS_Eisu = 0x66, // Not present in keycode usage? 149 | kVK_F11 = 0x67, 150 | kVK_JIS_Kana = 0x68, // Not present in keycode usage? 151 | kVK_F13 = 0x69, 152 | kVK_F16 = 0x6A, 153 | kVK_F14 = 0x6B, 154 | // 6C? 155 | kVK_F10 = 0x6D, 156 | kVK_ContextMenu = 0x6E, /* That strange key next to Alt Gr in Windows keyboards */ 157 | kVK_F12 = 0x6F, 158 | kVK_VidMirror = 0x70, // Not present in keycode usage? /* Toggle between extended desktop and clone mode */ 159 | kVK_F15 = 0x71, 160 | kVK_Help = 0x72, // Maybe Insert in different keyboard? Have to check 161 | kVK_Home = 0x73, 162 | kVK_PageUp = 0x74, 163 | kVK_ForwardDelete = 0x75, 164 | kVK_F4 = 0x76, 165 | kVK_End = 0x77, 166 | kVK_F2 = 0x78, 167 | kVK_PageDown = 0x79, 168 | kVK_F1 = 0x7A, 169 | kVK_LeftArrow = 0x7B, 170 | kVK_RightArrow = 0x7C, 171 | kVK_DownArrow = 0x7D, 172 | kVK_UpArrow = 0x7E, 173 | kVK_Power = 0x7F, // Maybe Menu in different keyboard? Wtf is menu? Have to check 174 | // 80? 175 | kVK_Spotlight = 0x81, // Not present in keycode usage? 176 | kVK_Dashboard = 0x82, // Not present in keycode usage? 177 | kVK_Launchpad = 0x83, // Not present in keycode usage? 178 | // 84 ~ 8F? 179 | kVK_BrightnessUp = 0x90, // Not present in keycode usage? 180 | kVK_BrightnessDown = 0x91, // Not present in keycode usage? 181 | kVK_Eject = 0x92, // Not present in keycode usage? 182 | // 93 ~ 9F? 183 | kVK_ExposesAll = 0xA0, // Not present in keycode usage? 184 | kVK_ExposesDesktop = 0xA1 // Not present in keycode usage? 185 | // A2 ~ FF? 186 | }; 187 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/VMMWebView.h: -------------------------------------------------------------------------------- 1 | // 2 | // VMMWebView.h 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 30/10/2017. 6 | // Copyright © 2017 VitorMM. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | #import "VMMView.h" 13 | #import "VMMComputerInformation.h" 14 | 15 | #define VMMWebViewSupportsHTML5 IS_SYSTEM_MAC_OS_10_9_OR_SUPERIOR 16 | 17 | @interface VMMWebViewNavigationBar : VMMView 18 | @property (nonatomic, strong, nullable) NSTextField* addressBarField; 19 | @property (nonatomic, strong, nullable) NSButton* refreshButton; 20 | @end 21 | 22 | @interface VMMWebView : VMMView 23 | 24 | @property (nonatomic) BOOL hideNavigationBar; 25 | @property (nonatomic) BOOL urlLoaded; 26 | @property (nonatomic) BOOL usingWkWebView; 27 | @property (nonatomic, strong, nullable) NSView* webView; 28 | @property (nonatomic, strong, nullable) VMMWebViewNavigationBar* navigationBar; 29 | @property (nonatomic, strong, nullable) NSTextField* webViewErrorLabel; 30 | 31 | @property (nonatomic, strong, nullable) NSURL* lastAccessedUrl; 32 | 33 | -(void)showErrorMessage:(nonnull NSString*)errorMessage; 34 | 35 | -(BOOL)loadURL:(nonnull NSURL*)url; 36 | -(BOOL)loadURLWithString:(nonnull NSString*)website; 37 | -(void)loadHTMLString:(nonnull NSString*)htmlPage; 38 | -(void)loadEmptyPage; 39 | 40 | @end 41 | 42 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/de.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | ObjectiveC_Extension 4 | 5 | Created by Vitor Marques de Miranda on 29/09/17. 6 | Copyright © 2017 VitorMM. All rights reserved. 7 | */ 8 | 9 | // Misc 10 | "OK" = "OK"; 11 | "Cancel" = "Abbrechen"; 12 | "Yes" = "Ja"; 13 | "No" = "Nein"; 14 | 15 | // NSAlert Extension 16 | "Success" = "Erfolg"; 17 | "Warning" = "Warnung"; 18 | "Error" = "Fehler"; 19 | 20 | // NSData Extension 21 | //"Error while reading file data: %@" = "Erro enquanto lia dados de arquivo: %@"; 22 | 23 | // NSString Extension 24 | "Error while reading file: %@" = "Fehler beim lesen der Datei: %@"; 25 | "Error while writting file: %@" = "Fehler beim schreiben der Datei: %@"; 26 | 27 | // NSFileManager Extension 28 | "Error while creating symbolic link: %@" = "Erro enquanto criava link simbólico: %@"; 29 | "Error while creating folder: %@" = "Fehler beim erstellen des Ordners: %@"; 30 | "Error while moving file: %@" = "Fehler beim bewegen der Datei: %@"; 31 | "Error while copying file: %@" = "Fehler beim kopieren der Datei: %@"; 32 | "Error while removing file: %@" = "Fehler beim entfernen der Datei: %@"; 33 | "Error while listing folder contents: %@" = "Fehler beim auflisten des Ordnerinhaltes von: %@"; 34 | //"Error while listing folder contents: %@ doesn't exist." = "Erro enquanto listava o conteúdo de pasta: %@ não existe."; 35 | //"Error while listing folder contents: %@ is not a folder." = "Erro enquanto listava o conteúdo de pasta: %@ não é uma pasta."; 36 | //"Error while retrieving symbolic link destination: %@" = "Erro enquanto obtia destino de link simbólico: %@"; 37 | 38 | // NSTask Extension 39 | //"Path for %@ not found." = "Caminho para %@ não encontrado."; 40 | //"File %@ not found." = "Arquivo %@ não encontrado."; 41 | //"File %@ not runnable." = "Arquivo %@ não é executável."; 42 | //"Directory %@ does not exists." = "Diretório %@ não existe."; 43 | 44 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/en.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | ObjectiveC_Extension 4 | 5 | Created by Vitor Marques de Miranda on 29/09/17. 6 | Copyright © 2017 VitorMM. All rights reserved. 7 | */ 8 | 9 | /* 10 | // Misc 11 | "OK" = "OK"; 12 | "Cancel" = "Cancelar"; 13 | "Yes" = "Sim"; 14 | "No" = "Não"; 15 | 16 | // VMMUsageKeycode 17 | "Error Roll Over" = "Encerramento de Erro"; 18 | "Post Fail" = "Pós-Falha"; 19 | "Error Undefined" = "Erro Indefinido"; 20 | "Return" = "Return"; 21 | "Escape" = "Esc"; 22 | "Delete" = "Delete"; 23 | "Tab" = "Tab"; 24 | "Space" = "Espaço"; 25 | "Minus" = "Menos"; 26 | "Equal" = "Igual"; 27 | "Left Bracket" = "Colchete Esquerdo"; 28 | "Right Bracket" = "Colchete Direito"; 29 | "Backslash" = "Contra-Barra"; 30 | "Pound" = "Libra"; 31 | "Semicolon" = "Ponto e vírgula"; 32 | "Quote" = "Aspas"; 33 | "Grave" = "Crase"; 34 | "Comma" = "Vírgula"; 35 | "Period" = "Ponto"; 36 | "Slash" = "Barra"; 37 | "Caps Lock" = "Caps Lock"; 38 | "Print Screen" = "Print Screen"; 39 | "Scroll Lock" = "Scroll Lock"; 40 | "Pause" = "Pause"; 41 | "Insert" = "Insert"; 42 | "Home" = "Home"; 43 | "Page Up" = "Page Up"; 44 | "Forward Delete" = "Forward Delete"; 45 | "End" = "End"; 46 | "Page Down" = "Page Down"; 47 | "Right Arrow" = "Seta Direita"; 48 | "Left Arrow" = "Seta Esquerda"; 49 | "Down Arrow" = "Seta Baixo"; 50 | "Up Arrow" = "Seta Cima"; 51 | "Keypad Clear" = ""; 52 | "Keypad Divide" = ""; 53 | "Keypad Multiply" = ""; 54 | "Keypad Minus" = ""; 55 | "Keypad Plus" = ""; 56 | "Keypad Enter" = ""; 57 | "Keypad 1" = ""; 58 | "Keypad 2" = ""; 59 | "Keypad 3" = ""; 60 | "Keypad 4" = ""; 61 | "Keypad 5" = ""; 62 | "Keypad 6" = ""; 63 | "Keypad 7" = ""; 64 | "Keypad 8" = ""; 65 | "Keypad 9" = ""; 66 | "Keypad 0" = ""; 67 | "Keypad Decimal" = ""; 68 | "Backslash" = ""; 69 | "Application" = ""; 70 | "Power" = ""; 71 | "Keypad Equals" = ""; 72 | "Execute" = ""; 73 | "Help" = ""; 74 | "Context Menu" = ""; 75 | "Select" = ""; 76 | "Stop" = ""; 77 | "Again" = ""; 78 | "Undo" = ""; 79 | "Cut" = ""; 80 | "Copy" = ""; 81 | "Paste" = ""; 82 | "Find" = ""; 83 | "Mute" = ""; 84 | "Volume Up" = ""; 85 | "Volume Down" = ""; 86 | "Locking Caps Lock" = ""; 87 | "Locking Num Lock" = ""; 88 | "Locking Scroll Lock" = ""; 89 | "Keypad Comma" = ""; 90 | "Keypad Equal" = ""; 91 | "Hangul/English" = ""; 92 | "Conversion Hanja" = ""; 93 | "Zankaku or Hankaku" = ""; 94 | "Alternate Erase" = ""; 95 | "SysReq or Attention" = ""; 96 | "Cancel" = ""; 97 | "Clear" = ""; 98 | "Prior" = ""; 99 | "Return" = ""; 100 | "Separator" = ""; 101 | "Out" = ""; 102 | "Oper" = ""; 103 | "Clear or Again" = ""; 104 | "CrSel or Props" = ""; 105 | "ExSel" = ""; 106 | "Keypad Zero Zero" = ""; 107 | "Keypad Zero Zero Zero" = ""; 108 | "Keypad Thousands Separator" = ""; 109 | "Keypad Decimal Separator" = ""; 110 | "Keypad Currency Unit" = ""; 111 | "Keypad Currency Subunit" = ""; 112 | "Keypad Left Parentheses" = ""; 113 | "Keypad Right Parentheses" = ""; 114 | "Keypad Left Braces" = ""; 115 | "Keypad Right Braces" = ""; 116 | "Keypad Tab" = ""; 117 | "Keypad Backspace" = ""; 118 | "Keypad A" = ""; 119 | "Keypad B" = ""; 120 | "Keypad C" = ""; 121 | "Keypad D" = ""; 122 | "Keypad E" = ""; 123 | "Keypad F" = ""; 124 | "Keypad XOR" = ""; 125 | "Keypad Circumflex" = ""; 126 | "Keypad Percent" = ""; 127 | "Keypad Less Than" = ""; 128 | "Keypad More Than" = ""; 129 | "Keypad Ampersand" = ""; 130 | "Keypad Ampersand Ampersand" = ""; 131 | "Keypad Vertical Line" = ""; 132 | "Keypad Two Vertical Lines" = ""; 133 | "Keypad Colon" = ""; 134 | "Keypad Number Sign" = ""; 135 | "Keypad Space" = ""; 136 | "Keypad Commercial At" = ""; 137 | "Keypad Exclamation" = ""; 138 | "Keypad Memory Store" = ""; 139 | "Keypad Memory Recall" = ""; 140 | "Keypad Memory Clear" = ""; 141 | "Keypad Memory Add" = ""; 142 | "Keypad Memory Substract" = ""; 143 | "Keypad Memory Multiply" = ""; 144 | "Keypad Memory Divide" = ""; 145 | "Keypad Plus Minus" = ""; 146 | "Keypad Clear" = ""; 147 | "Keypad Clear Entry" = ""; 148 | "Keypad Binary" = ""; 149 | "Keypad Octal" = ""; 150 | "Keypad Decimal" = ""; 151 | "Keypad Hexadecimal" = ""; 152 | "Left Control" = ""; 153 | "Left Shift" = ""; 154 | "Left Option" = ""; 155 | "Left Command" = ""; 156 | "Right Control" = ""; 157 | "Right Shift" = ""; 158 | "Right Option" = ""; 159 | "Right Command" = ""; 160 | "Play" = ""; 161 | "Function" = ""; 162 | "Next" = ""; 163 | "Previous" = ""; 164 | "Underscore" = ""; 165 | "Video Mirror" = ""; 166 | "Spotlight" = ""; 167 | "Dashboard" = ""; 168 | "Launchpad" = ""; 169 | "Brightness Up" = ""; 170 | "Brightness Down" = ""; 171 | "Eject" = ""; 172 | "Exposes All" = ""; 173 | "Exposes Desktop" = ""; 174 | 175 | // NSAlert Extension 176 | "Success" = "Sucesso"; 177 | "Warning" = "Aviso"; 178 | "Error" = "Erro"; 179 | 180 | // NSData Extension 181 | "Error while loading file data: %@" = "Erro enquanto carregava dados de arquivo: %@"; 182 | 183 | // NSFileManager Extension 184 | "Error while creating symbolic link: %@" = "Erro enquanto criava link simbólico: %@"; 185 | "Error while creating folder: %@" = "Erro enquanto criava pasta: %@"; 186 | "Error while moving file: %@" = "Erro enquanto movia arquivo: %@"; 187 | "Error while copying file: %@" = "Erro enquanto copiava arquivo: %@"; 188 | "Error while removing file: %@" = "Erro enquanto removia arquivo: %@"; 189 | "Error while listing folder contents: %@ doesn't exist." = "Erro enquanto listava o conteúdo de pasta: %@ não existe."; 190 | "Error while listing folder contents: %@ is not a folder." = "Erro enquanto listava o conteúdo de pasta: %@ não é uma pasta."; 191 | "Error while listing folder contents: %@" = "Erro enquanto listava o conteúdo de pasta: %@"; 192 | "Error while retrieving symbolic link destination: %@" = "Erro enquanto obtia destino de link simbólico: %@"; 193 | 194 | // NSString Extension 195 | "Error while reading file: %@" = "Erro enquanto lia arquivo: %@"; 196 | "Error while writting file: %@" = "Erro enquanto escrevia arquivo: %@"; 197 | 198 | // NSTask Extension 199 | "Path for %@ not found." = "Caminho para %@ não encontrado."; 200 | "File %@ not found." = "Arquivo %@ não encontrado."; 201 | "File %@ not runnable." = "Arquivo %@ não é executável."; 202 | "Directory %@ does not exists." = "Diretório %@ não existe."; 203 | 204 | // VMMWebView 205 | "You need Flash Player in order to watch YouTube videos in your macOS version" = "Você precisa do Flash Player para assistir vídeos do YouTube na sua versão do macOS"; 206 | "Invalid URL provided" = "URL inválida provida"; 207 | 208 | // VMMKeyCaptureField 209 | "Unknown Key (%d)" = "Tecla Desconhecida (%d)"; 210 | 211 | */ 212 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/fr.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | ObjectiveC_Extension 4 | 5 | Created by Vitor Marques de Miranda on 29/09/17. 6 | Copyright © 2017 VitorMM. All rights reserved. 7 | */ 8 | 9 | // Misc 10 | "OK" = "OK"; 11 | "Cancel" = "Annuler"; 12 | "Yes" = "Oui"; 13 | "No" = "Non"; 14 | 15 | // NSAlert Extension 16 | "Success" = "Succès"; 17 | "Warning" = "Attention"; 18 | "Error" = "Erreur"; 19 | 20 | // NSData Extension 21 | //"Error while reading file data: %@" = "Erro enquanto lia dados de arquivo: %@"; 22 | 23 | // NSString Extension 24 | "Error while reading file: %@" = "Erreur lors de la lecture du fichier: %@"; 25 | "Error while writting file: %@" = "Erreur lors de l'écriture du fichier: %@"; 26 | 27 | // NSFileManager Extension 28 | "Error while creating symbolic link: %@" = "Erreur lors de la création d'un lien symbolique: %@"; 29 | "Error while creating folder: %@" = "Erreur lors de la création du dossier: %@"; 30 | "Error while moving file: %@" = "Erreur lors du déplacement du fichier: %@"; 31 | "Error while copying file: %@" = "Erreur lors de la copie du fichier: %@"; 32 | "Error while removing file: %@" = "Erreur lors de la suppression du fichier: %@"; 33 | "Error while listing folder contents: %@" = "Erreur lors du listage du contenu du dossier: %@"; 34 | //"Error while listing folder contents: %@ doesn't exist." = "Erro enquanto listava o conteúdo de pasta: %@ não existe."; 35 | //"Error while listing folder contents: %@ is not a folder." = "Erro enquanto listava o conteúdo de pasta: %@ não é uma pasta."; 36 | //"Error while retrieving symbolic link destination: %@" = "Erro enquanto obtia destino de link simbólico: %@"; 37 | 38 | // NSTask Extension 39 | //"Path for %@ not found." = "Caminho para %@ não encontrado."; 40 | //"File %@ not found." = "Arquivo %@ não encontrado."; 41 | //"File %@ not runnable." = "Arquivo %@ não é executável."; 42 | //"Directory %@ does not exists." = "Diretório %@ não existe."; 43 | 44 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/nl.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | ObjectiveC_Extension 4 | 5 | Created by Vitor Marques de Miranda on 29/09/17. 6 | Copyright © 2017 VitorMM. All rights reserved. 7 | */ 8 | 9 | // Misc 10 | "OK" = "OK"; 11 | "Cancel" = "Annuleren"; 12 | "Yes" = "Ja"; 13 | "No" = "Nee"; 14 | 15 | // NSAlert Extension 16 | "Success" = "Success"; 17 | "Warning" = "Waarschuwing"; 18 | "Error" = "Error"; 19 | 20 | // NSData Extension 21 | //"Error while reading file data: %@" = "Erro enquanto lia dados de arquivo: %@"; 22 | 23 | // NSString Extension 24 | "Error while reading file: %@" = "Fout tijdens lezen van bestand: %@"; 25 | "Error while writting file: %@" = "Fout tijdens schrijven van bestand: %@"; 26 | 27 | // NSFileManager Extension 28 | "Error while creating symbolic link: %@" = "Fout tijdens aanmaken symbolische link: %@"; 29 | "Error while creating folder: %@" = "Fout tijdens aanmaken map: %@"; 30 | "Error while moving file: %@" = "Fout tijdens verplaatsen bestand: %@"; 31 | "Error while copying file: %@" = "Fout tijdens kopiëren bestand: %@"; 32 | "Error while removing file: %@" = "Fout tijdens verwijderen bestand: %@"; 33 | "Error while listing folder contents: %@" = "Fout tijdens opmaken inhoud folder: %@"; 34 | //"Error while listing folder contents: %@ doesn't exist." = "Erro enquanto listava o conteúdo de pasta: %@ não existe."; 35 | //"Error while listing folder contents: %@ is not a folder." = "Erro enquanto listava o conteúdo de pasta: %@ não é uma pasta."; 36 | "Error while retrieving symbolic link destination: %@" = "Error tijdens het checken van de symbolische link bestemming %@"; 37 | 38 | // NSTask Extension 39 | //"Path for %@ not found." = "Caminho para %@ não encontrado."; 40 | "File %@ not found." = "Bestand %@ niet gevonden."; 41 | "File %@ not runnable." = "Bestand %@ niet uitvoerbaar."; 42 | //"Directory %@ does not exists." = "Diretório %@ não existe."; 43 | 44 | -------------------------------------------------------------------------------- /ObjectiveC_Extension/pt-BR.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | ObjectiveC_Extension 4 | 5 | Created by Vitor Marques de Miranda on 29/09/17. 6 | Copyright © 2017 VitorMM. All rights reserved. 7 | */ 8 | 9 | // Misc 10 | "OK" = "OK"; 11 | "Cancel" = "Cancelar"; 12 | "Yes" = "Sim"; 13 | "No" = "Não"; 14 | 15 | // NSAlert Extension 16 | "Success" = "Sucesso"; 17 | "Warning" = "Aviso"; 18 | "Error" = "Erro"; 19 | 20 | // NSData Extension 21 | "Error while reading file data: %@" = "Erro enquanto lia dados de arquivo: %@"; 22 | 23 | // NSString Extension 24 | "Error while reading file: %@" = "Erro enquanto lia arquivo: %@"; 25 | "Error while writting file: %@" = "Erro enquanto escrevia arquivo: %@"; 26 | 27 | // NSFileManager Extension 28 | "Error while creating symbolic link: %@" = "Erro enquanto criava link simbólico: %@"; 29 | "Error while creating folder: %@" = "Erro enquanto criava pasta: %@"; 30 | "Error while moving file: %@" = "Erro enquanto movia arquivo: %@"; 31 | "Error while copying file: %@" = "Erro enquanto copiava arquivo: %@"; 32 | "Error while removing file: %@" = "Erro enquanto removia arquivo: %@"; 33 | "Error while listing folder contents: %@" = "Erro enquanto listava o conteúdo de pasta: %@"; 34 | "Error while listing folder contents: %@ doesn't exist." = "Erro enquanto listava o conteúdo de pasta: %@ não existe."; 35 | "Error while listing folder contents: %@ is not a folder." = "Erro enquanto listava o conteúdo de pasta: %@ não é uma pasta."; 36 | "Error while retrieving symbolic link destination: %@" = "Erro enquanto obtia destino de link simbólico: %@"; 37 | 38 | // NSTask Extension 39 | "Path for %@ not found." = "Caminho para %@ não encontrado."; 40 | "File %@ not found." = "Arquivo %@ não encontrado."; 41 | "File %@ not runnable." = "Arquivo %@ não é executável."; 42 | "Directory %@ does not exists." = "Diretório %@ não existe."; 43 | 44 | -------------------------------------------------------------------------------- /ObjectiveC_ExtensionTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /ObjectiveC_ExtensionTests/NSArrayTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSArrayTests.m 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 15/05/17. 6 | // Copyright © 2017 Vitor Marques de Miranda. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "NSArray+Extension.h" 11 | 12 | @interface NSArrayTests : XCTestCase 13 | 14 | @end 15 | 16 | @implementation NSArrayTests 17 | 18 | - (void)testSortedDictionariesArrayWithKeyOrderingByValuesOrder 19 | { 20 | NSString* key = @"Bus"; 21 | NSArray* order = @[@"PCIe", @"PCI", @"Built-In"]; 22 | 23 | NSMutableArray* input = [@[@{key: @"PCIe"}, @{key: @"Built-In"}, @{key: @"PCI"}] mutableCopy]; 24 | NSArray* output = @[@{key: @"PCIe"}, @{key: @"PCI"}, @{key: @"Built-In"}]; 25 | 26 | [input sortDictionariesWithKey:key orderingByValuesOrder:order]; 27 | XCTAssert([input isEqualToArray:output]); 28 | } 29 | 30 | - (void)testArrayByRemovingRepetitions_noChange 31 | { 32 | NSArray* originalArray = @[@1,@2,@3,@4,@5,@6]; 33 | NSArray* resultArray = [originalArray arrayByRemovingRepetitions]; 34 | 35 | XCTAssert(resultArray.count == 6); 36 | XCTAssert([resultArray containsObject:@1]); 37 | XCTAssert([resultArray containsObject:@2]); 38 | XCTAssert([resultArray containsObject:@3]); 39 | XCTAssert([resultArray containsObject:@4]); 40 | XCTAssert([resultArray containsObject:@5]); 41 | XCTAssert([resultArray containsObject:@6]); 42 | } 43 | - (void)testArrayByRemovingRepetitions_fromSixToThreeResults 44 | { 45 | NSArray* originalArray = @[@1,@2,@1,@2,@1,@4]; 46 | NSArray* resultArray = [originalArray arrayByRemovingRepetitions]; 47 | 48 | XCTAssert(resultArray.count == 3); 49 | XCTAssert([resultArray containsObject:@1]); 50 | XCTAssert([resultArray containsObject:@2]); 51 | XCTAssert([resultArray containsObject:@4]); 52 | } 53 | - (void)testArrayByRemovingRepetitions_oneResultOnly 54 | { 55 | NSArray* originalArray = @[@1,@1,@1,@1,@1,@1]; 56 | NSArray* resultArray = [originalArray arrayByRemovingRepetitions]; 57 | 58 | XCTAssert(resultArray.count == 1); 59 | XCTAssert([resultArray containsObject:@1]); 60 | } 61 | 62 | - (void)testArrayByRemovingObjectsFromArray_removeTwoFromFive 63 | { 64 | NSArray* originalArray = @[@1,@2,@3,@4,@5]; 65 | NSArray* itemsToRemove = @[@2,@5]; 66 | NSArray* result = [originalArray arrayByRemovingObjectsFromArray:itemsToRemove]; 67 | 68 | XCTAssert(resultArray.count == 3); 69 | XCTAssert([resultArray containsObject:@1]); 70 | XCTAssert([resultArray containsObject:@3]); 71 | XCTAssert([resultArray containsObject:@4]); 72 | } 73 | - (void)testArrayByRemovingObjectsFromArray_removeAll 74 | { 75 | NSArray* originalArray = @[@1,@2,@3,@4,@5]; 76 | NSArray* itemsToRemove = @[@4,@3,@2,@1,@5]; 77 | NSArray* result = [originalArray arrayByRemovingObjectsFromArray:itemsToRemove]; 78 | 79 | XCTAssert(resultArray.count == 0); 80 | } 81 | - (void)testArrayByRemovingObjectsFromArray_removeNothing 82 | { 83 | NSArray* originalArray = @[@1,@2,@3,@4,@5]; 84 | NSArray* itemsToRemove = @[@7,@8]; 85 | NSArray* result = [originalArray arrayByRemovingObjectsFromArray:itemsToRemove]; 86 | 87 | XCTAssert(resultArray.count == 5); 88 | XCTAssert([resultArray containsObject:@1]); 89 | XCTAssert([resultArray containsObject:@2]); 90 | XCTAssert([resultArray containsObject:@3]); 91 | XCTAssert([resultArray containsObject:@4]); 92 | XCTAssert([resultArray containsObject:@5]); 93 | } 94 | 95 | @end 96 | -------------------------------------------------------------------------------- /ObjectiveC_ExtensionTests/NSColorTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSColorTests.m 3 | // ObjectiveC_ExtensionTests 4 | // 5 | // Created by Vitor Marques de Miranda on 14/11/2017. 6 | // Copyright © 2017 VitorMM. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "NSColor+Extension.h" 11 | 12 | @interface NSColorTests : XCTestCase 13 | 14 | @end 15 | 16 | @implementation NSColorTests 17 | 18 | -(void)testColorWithHexColorString 19 | { 20 | NSColor* redColor = [NSColor colorWithHexColorString:@"FF0000"]; 21 | 22 | XCTAssert(redColor.redComponent - 255 < 0.1); 23 | XCTAssert(redColor.greenComponent < 0.1); 24 | XCTAssert(redColor.blueComponent < 0.1); 25 | } 26 | -(void)testHexColorString 27 | { 28 | NSColor* redColor = [NSColor redColor]; 29 | NSString* redColorHex = [redColor hexColorString]; 30 | 31 | XCTAssert([redColorHex isEqualToString:@"FF0000"]); 32 | } 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /ObjectiveC_ExtensionTests/NSStringTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSStringTests.m 3 | // ObjectiveC_Extension 4 | // 5 | // Created by Vitor Marques de Miranda on 15/05/17. 6 | // Copyright © 2017 Vitor Marques de Miranda. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "NSString+Extension.h" 11 | 12 | @interface NSStringTests : XCTestCase 13 | 14 | @end 15 | 16 | @implementation NSStringTests 17 | 18 | - (void)testStringContains 19 | { 20 | XCTAssert(![@"12345678" contains:@""]); 21 | XCTAssert( [@"12345678" contains:@"123"]); 22 | XCTAssert(![@"12345678" contains:@"321"]); 23 | } 24 | 25 | - (void)testStringWithHexString 26 | { 27 | XCTAssert([[NSString stringWithHexadecimalUTF8String:@"42"] isEqualToString:@"B"]); 28 | } 29 | 30 | - (void)testStringByRemovingEvenCharsFromString 31 | { 32 | XCTAssert([[NSString stringByRemovingEvenCharsFromString:@"12345678"] isEqualToString:@"1357"]); 33 | } 34 | 35 | - (void)testStringWebStructure 36 | { 37 | XCTAssert([[@"?" stringToWebStructure] isEqualToString:@"%3F"]); 38 | XCTAssert([[@"<" stringToWebStructure] isEqualToString:@"%3C"]); 39 | XCTAssert([[@"&" stringToWebStructure] isEqualToString:@"%26"]); 40 | XCTAssert([[@"%" stringToWebStructure] isEqualToString:@"%25"]); 41 | XCTAssert([[@" " stringToWebStructure] isEqualToString:@"%20"]); 42 | 43 | XCTAssert([[@"\n" stringToWebStructure] isEqualToString:@"%0A"]); 44 | XCTAssert([[@"\t" stringToWebStructure] isEqualToString:@"%09"]); 45 | 46 | XCTAssert([[@"B" stringToWebStructure] isEqualToString:@"B"]); 47 | XCTAssert([[@"+" stringToWebStructure] isEqualToString:@"%2B"]); 48 | XCTAssert([[@"=" stringToWebStructure] isEqualToString:@"%3D"]); 49 | } 50 | 51 | - (void)testStringRangeAfterAndBefore 52 | { 53 | // With Before and End in the String; With Before and End arguments 54 | XCTAssert([@"012345678X0123Y5" rangeAfterString:@"X" andBeforeString:@"Y"].location == 10); 55 | XCTAssert([@"012345678X0123Y5" rangeAfterString:@"X" andBeforeString:@"Y"].length == 4); 56 | 57 | // With Before and End in the String; With Before argument only 58 | XCTAssert([@"012345678X0123Y5" rangeAfterString:@"X" andBeforeString:nil].location == 10); 59 | XCTAssert([@"012345678X0123Y5" rangeAfterString:@"X" andBeforeString:nil].length == 6); 60 | 61 | // With Before and End in the String; With After argument only 62 | XCTAssert([@"012345678X0123Y5" rangeAfterString:nil andBeforeString:@"Y"].location == 0); 63 | XCTAssert([@"012345678X0123Y5" rangeAfterString:nil andBeforeString:@"Y"].length == 14); 64 | 65 | // With Before and End in the String; With no arguments 66 | XCTAssert([@"012345678X0123Y5" rangeAfterString:nil andBeforeString:nil].location == 0); 67 | XCTAssert([@"012345678X0123Y5" rangeAfterString:nil andBeforeString:nil].length == 16); 68 | 69 | 70 | 71 | // With Before in the String; With Before and End arguments 72 | XCTAssert([@"012345678X012345" rangeAfterString:@"X" andBeforeString:@"Y"].location == 10); 73 | XCTAssert([@"012345678X012345" rangeAfterString:@"X" andBeforeString:@"Y"].length == 6); 74 | 75 | // With Before in the String; With Before argument only 76 | XCTAssert([@"012345678X012345" rangeAfterString:@"X" andBeforeString:nil].location == 10); 77 | XCTAssert([@"012345678X012345" rangeAfterString:@"X" andBeforeString:nil].length == 6); 78 | 79 | // With Before in the String; With After argument only 80 | XCTAssert([@"012345678X012345" rangeAfterString:nil andBeforeString:@"Y"].location == 0); 81 | XCTAssert([@"012345678X012345" rangeAfterString:nil andBeforeString:@"Y"].length == 16); 82 | 83 | // With Before in the String; With no arguments 84 | XCTAssert([@"012345678X012345" rangeAfterString:nil andBeforeString:nil].location == 0); 85 | XCTAssert([@"012345678X012345" rangeAfterString:nil andBeforeString:nil].length == 16); 86 | 87 | 88 | 89 | // With End in the String; With Before and End arguments 90 | XCTAssert([@"01234567890123Y5" rangeAfterString:@"X" andBeforeString:@"Y"].location == NSNotFound); 91 | 92 | // With End in the String; With Before argument only 93 | XCTAssert([@"01234567890123Y5" rangeAfterString:@"X" andBeforeString:nil].location == NSNotFound); 94 | 95 | // With End in the String; With After argument only 96 | XCTAssert([@"01234567890123Y5" rangeAfterString:nil andBeforeString:@"Y"].location == 0); 97 | XCTAssert([@"01234567890123Y5" rangeAfterString:nil andBeforeString:@"Y"].length == 14); 98 | 99 | // With End in the String; With no arguments 100 | XCTAssert([@"01234567890123Y5" rangeAfterString:nil andBeforeString:nil].location == 0); 101 | XCTAssert([@"01234567890123Y5" rangeAfterString:nil andBeforeString:nil].length == 16); 102 | 103 | 104 | 105 | // With End in the String; With Before and End arguments 106 | XCTAssert([@"0123456789012345" rangeAfterString:@"X" andBeforeString:@"Y"].location == NSNotFound); 107 | 108 | // With End in the String; With Before argument only 109 | XCTAssert([@"0123456789012345" rangeAfterString:@"X" andBeforeString:nil].location == NSNotFound); 110 | 111 | // With End in the String; With After argument only 112 | XCTAssert([@"0123456789012345" rangeAfterString:nil andBeforeString:@"Y"].location == 0); 113 | XCTAssert([@"0123456789012345" rangeAfterString:nil andBeforeString:@"Y"].length == 16); 114 | 115 | // With End in the String; With no arguments 116 | XCTAssert([@"0123456789012345" rangeAfterString:nil andBeforeString:nil].location == 0); 117 | XCTAssert([@"0123456789012345" rangeAfterString:nil andBeforeString:nil].length == 16); 118 | } 119 | 120 | - (void)testInitialIntValue 121 | { 122 | XCTAssert([@"10421ab" initialIntegerValue].intValue == 10421); 123 | XCTAssert([@"10421a" initialIntegerValue].intValue == 10421); 124 | XCTAssert([@"10421&" initialIntegerValue].intValue == 10421); 125 | XCTAssert([@"10421." initialIntegerValue].intValue == 10421); 126 | XCTAssert([@"10421%" initialIntegerValue].intValue == 10421); 127 | XCTAssert([@"10421" initialIntegerValue].intValue == 10421); 128 | XCTAssert([@"abc" initialIntegerValue] == nil ); 129 | } 130 | 131 | - (void)testGetFragment 132 | { 133 | // With Before and End in the String; With Before and End arguments 134 | XCTAssert([[@"012345678X0123Y5" getFragmentAfter:@"X" andBefore:@"Y"] isEqualToString:@"0123"]); 135 | 136 | // With Before and End in the String; With Before argument only 137 | XCTAssert([[@"012345678X0123Y5" getFragmentAfter:@"X" andBefore:nil] isEqualToString:@"0123Y5"]); 138 | 139 | // With Before and End in the String; With After argument only 140 | XCTAssert([[@"012345678X0123Y5" getFragmentAfter:nil andBefore:@"Y"] isEqualToString:@"012345678X0123"]); 141 | 142 | // With Before and End in the String; With no arguments 143 | XCTAssert([[@"012345678X0123Y5" getFragmentAfter:nil andBefore:nil] isEqualToString:@"012345678X0123Y5"]); 144 | 145 | 146 | 147 | // With Before in the String; With Before and End arguments 148 | XCTAssert([[@"012345678X012345" getFragmentAfter:@"X" andBefore:@"Y"] isEqualToString:@"012345"]); 149 | 150 | // With Before in the String; With Before argument only 151 | XCTAssert([[@"012345678X012345" getFragmentAfter:@"X" andBefore:nil] isEqualToString:@"012345"]); 152 | 153 | // With Before in the String; With After argument only 154 | XCTAssert([[@"012345678X012345" getFragmentAfter:nil andBefore:@"Y"] isEqualToString:@"012345678X012345"]); 155 | 156 | // With Before in the String; With no arguments 157 | XCTAssert([[@"012345678X012345" getFragmentAfter:nil andBefore:nil] isEqualToString:@"012345678X012345"]); 158 | 159 | 160 | 161 | // With End in the String; With Before and End arguments 162 | XCTAssert([@"01234567890123Y5" getFragmentAfter:@"X" andBefore:@"Y"] == nil); 163 | 164 | // With End in the String; With Before argument only 165 | XCTAssert([@"01234567890123Y5" getFragmentAfter:@"X" andBefore:nil] == nil); 166 | 167 | // With End in the String; With After argument only 168 | XCTAssert([[@"01234567890123Y5" getFragmentAfter:nil andBefore:@"Y"] isEqualToString:@"01234567890123"]); 169 | 170 | // With End in the String; With no arguments 171 | XCTAssert([[@"01234567890123Y5" getFragmentAfter:nil andBefore:nil] isEqualToString:@"01234567890123Y5"]); 172 | 173 | 174 | 175 | // Without both in the String; With Before and End arguments 176 | XCTAssert([@"0123456789012345" getFragmentAfter:@"X" andBefore:@"Y"] == nil); 177 | 178 | // Without both in the String; With Before argument only 179 | XCTAssert([@"0123456789012345" getFragmentAfter:@"X" andBefore:nil] == nil); 180 | 181 | // Without both in the String; With After argument only 182 | XCTAssert([[@"0123456789012345" getFragmentAfter:nil andBefore:@"Y"] isEqualToString:@"0123456789012345"]); 183 | 184 | // Without both in the String; With no arguments 185 | XCTAssert([[@"0123456789012345" getFragmentAfter:nil andBefore:nil] isEqualToString:@"0123456789012345"]); 186 | } 187 | 188 | - (void)testComponentsMatchingWithRegex 189 | { 190 | NSArray* result; 191 | 192 | result = @[@"1",@"2",@"3",@"4",@"5",@"6",@"7",@"8",@"9",@"0"]; 193 | XCTAssert([[@"1234567890" componentsMatchingWithRegex:@"[0-9]"] isEqualToArray:result]); 194 | 195 | result = @[@"1234567890"]; 196 | XCTAssert([[@"1234567890" componentsMatchingWithRegex:@"[0-9]{10}"] isEqualToArray:result]); 197 | 198 | result = @[@"123a",@"456b",@"789c"]; 199 | XCTAssert([[@"123a456b789c" componentsMatchingWithRegex:@"[0-9]{3}[a-z]"] isEqualToArray:result]); 200 | 201 | result = @[@"1234567890"]; 202 | XCTAssert([[@"1234567890" componentsMatchingWithRegex:@"[0-9]+"] isEqualToArray:result]); 203 | } 204 | 205 | @end 206 | -------------------------------------------------------------------------------- /ObjectiveC_ExtensionTests/ObjectiveC_ExtensionTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // ObjectiveC_ExtensionTests.m 3 | // ObjectiveC_ExtensionTests 4 | // 5 | // Created by Vitor Marques de Miranda on 29/09/17. 6 | // Copyright © 2017 VitorMM. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ObjectiveC_ExtensionTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation ObjectiveC_ExtensionTests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | // Put setup code here. This method is called before the invocation of each test method in the class. 20 | } 21 | 22 | - (void)tearDown { 23 | // Put teardown code here. This method is called after the invocation of each test method in the class. 24 | [super tearDown]; 25 | } 26 | 27 | - (void)testExample { 28 | // This is an example of a functional test case. 29 | // Use XCTAssert and related functions to verify your tests produce the correct results. 30 | } 31 | 32 | - (void)testPerformanceExample { 33 | // This is an example of a performance test case. 34 | [self measureBlock:^{ 35 | // Put the code you want to measure the time of here. 36 | }]; 37 | } 38 | 39 | @end 40 | --------------------------------------------------------------------------------