├── .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 |
--------------------------------------------------------------------------------