Skip to content

Commit 4c003b7

Browse files
authored
Merge pull request #218 from apptentive/branch_5.1.1
Release 5.1.1
2 parents 284ee76 + f340d2a commit 4c003b7

18 files changed

+472
-14
lines changed

Apptentive/Apptentive.xcodeproj/project.pbxproj

+30-6
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,10 @@
387387
EF18124D1E8084C80053BD68 /* ApptentiveSafeCollections.m in Sources */ = {isa = PBXBuildFile; fileRef = EF18124A1E8084C80053BD68 /* ApptentiveSafeCollections.m */; };
388388
EF3063A91F2A8353004B4EB9 /* ApptentivePayloadDebug.h in Headers */ = {isa = PBXBuildFile; fileRef = EF3063A71F2A8353004B4EB9 /* ApptentivePayloadDebug.h */; };
389389
EF3063AA1F2A8353004B4EB9 /* ApptentivePayloadDebug.m in Sources */ = {isa = PBXBuildFile; fileRef = EF3063A81F2A8353004B4EB9 /* ApptentivePayloadDebug.m */; };
390+
EF3FE88A20A2270000A3C9C5 /* ApptentiveApptimize.h in Headers */ = {isa = PBXBuildFile; fileRef = EF3FE88820A2270000A3C9C5 /* ApptentiveApptimize.h */; };
391+
EF3FE88B20A2270000A3C9C5 /* ApptentiveApptimize.m in Sources */ = {isa = PBXBuildFile; fileRef = EF3FE88920A2270000A3C9C5 /* ApptentiveApptimize.m */; };
392+
EF3FE88E20A2285700A3C9C5 /* ApptentiveInvocation.h in Headers */ = {isa = PBXBuildFile; fileRef = EF3FE88C20A2285700A3C9C5 /* ApptentiveInvocation.h */; };
393+
EF3FE88F20A2285700A3C9C5 /* ApptentiveInvocation.m in Sources */ = {isa = PBXBuildFile; fileRef = EF3FE88D20A2285700A3C9C5 /* ApptentiveInvocation.m */; };
390394
EF43D89E1FD5EBBB00C0FF9F /* ApptentiveDispatchQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = EF43D89C1FD5EBBA00C0FF9F /* ApptentiveDispatchQueue.h */; };
391395
EF43D89F1FD5EBBB00C0FF9F /* ApptentiveDispatchQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = EF43D89D1FD5EBBB00C0FF9F /* ApptentiveDispatchQueue.m */; };
392396
EF43D8AA1FD5FE6D00C0FF9F /* ApptentiveGCDDispatchQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = EF43D8A81FD5FE6D00C0FF9F /* ApptentiveGCDDispatchQueue.m */; };
@@ -855,6 +859,10 @@
855859
EF3063A71F2A8353004B4EB9 /* ApptentivePayloadDebug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ApptentivePayloadDebug.h; sourceTree = "<group>"; };
856860
EF3063A81F2A8353004B4EB9 /* ApptentivePayloadDebug.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ApptentivePayloadDebug.m; sourceTree = "<group>"; };
857861
EF37099C1EDE19F300CFC5E5 /* ApptentiveDefines.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ApptentiveDefines.h; sourceTree = "<group>"; };
862+
EF3FE88820A2270000A3C9C5 /* ApptentiveApptimize.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ApptentiveApptimize.h; sourceTree = "<group>"; };
863+
EF3FE88920A2270000A3C9C5 /* ApptentiveApptimize.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ApptentiveApptimize.m; sourceTree = "<group>"; };
864+
EF3FE88C20A2285700A3C9C5 /* ApptentiveInvocation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ApptentiveInvocation.h; sourceTree = "<group>"; };
865+
EF3FE88D20A2285700A3C9C5 /* ApptentiveInvocation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ApptentiveInvocation.m; sourceTree = "<group>"; };
858866
EF43D89C1FD5EBBA00C0FF9F /* ApptentiveDispatchQueue.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ApptentiveDispatchQueue.h; sourceTree = "<group>"; };
859867
EF43D89D1FD5EBBB00C0FF9F /* ApptentiveDispatchQueue.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ApptentiveDispatchQueue.m; sourceTree = "<group>"; };
860868
EF43D8A81FD5FE6D00C0FF9F /* ApptentiveGCDDispatchQueue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ApptentiveGCDDispatchQueue.m; sourceTree = "<group>"; };
@@ -1018,6 +1026,7 @@
10181026
01A2CF931E49062700C2103A /* Apptentive */ = {
10191027
isa = PBXGroup;
10201028
children = (
1029+
EF3FE88720A226EE00A3C9C5 /* Apptimize */,
10211030
01A2CFB01E490A9700C2103A /* Custom Views */,
10221031
01A2CFBB1E490A9700C2103A /* Engagement */,
10231032
01A2D0021E490A9700C2103A /* Images */,
@@ -1482,6 +1491,8 @@
14821491
EF4EAB8C203F876A003318C9 /* ApptentiveDispatchTask.m */,
14831492
EF43D8A91FD5FE6D00C0FF9F /* ApptentiveGCDDispatchQueue.h */,
14841493
EF43D8A81FD5FE6D00C0FF9F /* ApptentiveGCDDispatchQueue.m */,
1494+
EF3FE88C20A2285700A3C9C5 /* ApptentiveInvocation.h */,
1495+
EF3FE88D20A2285700A3C9C5 /* ApptentiveInvocation.m */,
14851496
01A2D08B1E490A9700C2103A /* ApptentiveJSONSerialization.h */,
14861497
01A2D08C1E490A9700C2103A /* ApptentiveJSONSerialization.m */,
14871498
EF8EE3A91EBBA5D00033E7A1 /* ApptentiveJWT.h */,
@@ -1751,6 +1762,15 @@
17511762
path = Model;
17521763
sourceTree = "<group>";
17531764
};
1765+
EF3FE88720A226EE00A3C9C5 /* Apptimize */ = {
1766+
isa = PBXGroup;
1767+
children = (
1768+
EF3FE88820A2270000A3C9C5 /* ApptentiveApptimize.h */,
1769+
EF3FE88920A2270000A3C9C5 /* ApptentiveApptimize.m */,
1770+
);
1771+
path = Apptimize;
1772+
sourceTree = "<group>";
1773+
};
17541774
EF4EABA22040A8C5003318C9 /* utils */ = {
17551775
isa = PBXGroup;
17561776
children = (
@@ -1796,6 +1816,7 @@
17961816
01A2D0F81E490A9700C2103A /* Apptentive_Private.h in Headers */,
17971817
01A2D1DE1E490A9700C2103A /* ApptentiveSurveyAnswer.h in Headers */,
17981818
01E8E2361E6E096D00786738 /* ApptentiveInteractionAppleRatingDialogController.h in Headers */,
1819+
EF3FE88A20A2270000A3C9C5 /* ApptentiveApptimize.h in Headers */,
17991820
01A2D1DA1E490A9700C2103A /* ApptentiveReachability.h in Headers */,
18001821
01A2D1851E490A9700C2103A /* ApptentiveAttachmentCell.h in Headers */,
18011822
01A2D1191E490A9700C2103A /* ApptentiveInteractionSurveyController.h in Headers */,
@@ -1885,6 +1906,7 @@
18851906
EF18124B1E8084C80053BD68 /* ApptentiveSafeCollections.h in Headers */,
18861907
01A2D1A11E490A9700C2103A /* ApptentiveJSONSerialization.h in Headers */,
18871908
01A2D13B1E490A9700C2103A /* ApptentiveSDK.h in Headers */,
1909+
EF3FE88E20A2285700A3C9C5 /* ApptentiveInvocation.h in Headers */,
18881910
EF18123F1E807FC00053BD68 /* ApptentiveAssert.h in Headers */,
18891911
4D536E361EFC6690000EA45D /* ApptentiveNewLoginRequest.h in Headers */,
18901912
01A2D1071E490A9700C2103A /* ApptentiveInteractionController.h in Headers */,
@@ -2215,6 +2237,7 @@
22152237
4D4B36251F01892A005C7EC0 /* ApptentiveEngagementBackend.m in Sources */,
22162238
01A2D12C1E490A9700C2103A /* ApptentiveInteraction.m in Sources */,
22172239
01A50EC51FC5FFB00058C06C /* ApptentiveInvocations.m in Sources */,
2240+
EF3FE88B20A2270000A3C9C5 /* ApptentiveApptimize.m in Sources */,
22182241
EF43D89F1FD5EBBB00C0FF9F /* ApptentiveDispatchQueue.m in Sources */,
22192242
012ED92A2072F33F003D87F3 /* ApptentiveRetryPolicy.m in Sources */,
22202243
EF8EE3AC1EBBA5D00033E7A1 /* ApptentiveJWT.m in Sources */,
@@ -2280,6 +2303,7 @@
22802303
01A2D0F91E490A9700C2103A /* Apptentive.m in Sources */,
22812304
01A2D1811E490A9700C2103A /* ApptentiveMessageCenterViewController.m in Sources */,
22822305
01A2D11C1E490A9700C2103A /* ApptentiveInteractionUpgradeMessageController.m in Sources */,
2306+
EF3FE88F20A2285700A3C9C5 /* ApptentiveInvocation.m in Sources */,
22832307
01A2D1911E490A9700C2103A /* ApptentiveMessageCenterGreetingView.m in Sources */,
22842308
01A2D13A1E490A9700C2103A /* ApptentivePerson.m in Sources */,
22852309
01A2D13E1E490A9700C2103A /* ApptentiveConversation.m in Sources */,
@@ -2453,7 +2477,7 @@
24532477
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
24542478
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
24552479
COPY_PHASE_STRIP = NO;
2456-
CURRENT_PROJECT_VERSION = 11;
2480+
CURRENT_PROJECT_VERSION = 14;
24572481
DEBUG_INFORMATION_FORMAT = dwarf;
24582482
ENABLE_STRICT_OBJC_MSGSEND = YES;
24592483
ENABLE_TESTABILITY = YES;
@@ -2511,7 +2535,7 @@
25112535
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
25122536
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
25132537
COPY_PHASE_STRIP = NO;
2514-
CURRENT_PROJECT_VERSION = 11;
2538+
CURRENT_PROJECT_VERSION = 14;
25152539
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
25162540
ENABLE_NS_ASSERTIONS = NO;
25172541
ENABLE_STRICT_OBJC_MSGSEND = YES;
@@ -2543,7 +2567,7 @@
25432567
DEFINES_MODULE = YES;
25442568
DEVELOPMENT_TEAM = 86WML2UN43;
25452569
DYLIB_COMPATIBILITY_VERSION = 1;
2546-
DYLIB_CURRENT_VERSION = 11;
2570+
DYLIB_CURRENT_VERSION = 14;
25472571
DYLIB_INSTALL_NAME_BASE = "@rpath";
25482572
GCC_PREFIX_HEADER = "Apptentive/Misc/ApptentiveConnect-Prefix.pch";
25492573
GCC_PREPROCESSOR_DEFINITIONS = "APPTENTIVE_DEBUG=1";
@@ -2565,7 +2589,7 @@
25652589
DEFINES_MODULE = YES;
25662590
DEVELOPMENT_TEAM = 86WML2UN43;
25672591
DYLIB_COMPATIBILITY_VERSION = 1;
2568-
DYLIB_CURRENT_VERSION = 11;
2592+
DYLIB_CURRENT_VERSION = 14;
25692593
DYLIB_INSTALL_NAME_BASE = "@rpath";
25702594
GCC_PREFIX_HEADER = "Apptentive/Misc/ApptentiveConnect-Prefix.pch";
25712595
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
@@ -2616,7 +2640,7 @@
26162640
DEFINES_MODULE = YES;
26172641
DEVELOPMENT_TEAM = 86WML2UN43;
26182642
DYLIB_COMPATIBILITY_VERSION = 1;
2619-
DYLIB_CURRENT_VERSION = 11;
2643+
DYLIB_CURRENT_VERSION = 14;
26202644
DYLIB_INSTALL_NAME_BASE = "@rpath";
26212645
INFOPLIST_FILE = ApptentiveDebugging/Info.plist;
26222646
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
@@ -2635,7 +2659,7 @@
26352659
DEFINES_MODULE = YES;
26362660
DEVELOPMENT_TEAM = 86WML2UN43;
26372661
DYLIB_COMPATIBILITY_VERSION = 1;
2638-
DYLIB_CURRENT_VERSION = 11;
2662+
DYLIB_CURRENT_VERSION = 14;
26392663
DYLIB_INSTALL_NAME_BASE = "@rpath";
26402664
INFOPLIST_FILE = ApptentiveDebugging/Info.plist;
26412665
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";

Apptentive/Apptentive/Apptentive.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ FOUNDATION_EXPORT double ApptentiveVersionNumber;
2020
FOUNDATION_EXPORT const unsigned char ApptentiveVersionString[];
2121

2222
/** The version number of the Apptentive SDK. */
23-
#define kApptentiveVersionString @"5.1.0"
23+
#define kApptentiveVersionString @"5.1.1"
2424

2525
/** The version number of the Apptentive API platform. */
2626
#define kApptentiveAPIVersionString @"9"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
//
2+
// ApptentiveApptimize.h
3+
// Apptentive
4+
//
5+
// Created by Alex Lementuev on 5/8/18.
6+
// Copyright © 2018 Apptentive, Inc. All rights reserved.
7+
//
8+
9+
#import <Foundation/Foundation.h>
10+
11+
NS_ASSUME_NONNULL_BEGIN
12+
13+
@class ApptentiveApptimizeTestInfo;
14+
15+
extern NSNotificationName const ApptimizeTestsProcessedNotification;
16+
extern NSNotificationName const ApptentiveApptimizeTestRunNotification;
17+
extern NSString * const ApptentiveApptimizeTestNameUserInfoKey;
18+
extern NSString * const ApptentiveApptimizeVariantNameUserInfoKey;
19+
20+
@interface ApptentiveApptimize : NSObject
21+
22+
/**
23+
@return `YES` if Apptimize SDK is integrated with the host app.
24+
*/
25+
+ (BOOL)isApptimizeSDKAvailable;
26+
27+
/**
28+
@return Returns the version number of the Apptimize library as a string formatted as *major.minor.build* (e.g., 3.0.1).
29+
*/
30+
+ (nullable NSString *)libraryVersion;
31+
32+
/**
33+
@return `YES` is Apptimize SDK library version is supported.
34+
*/
35+
+ (BOOL)isSupportedLibraryVersion;
36+
37+
+ (nullable NSDictionary<NSString *, ApptentiveApptimizeTestInfo*> *)testInfo;
38+
39+
@end
40+
41+
/**
42+
* Data container class that mimics `ApptimizeTestInfo`.
43+
* https://sdk.apptimize.com/ios/appledocs/appledoc-3.0.1/Protocols/ApptimizeTestInfo.html
44+
*/
45+
@interface ApptentiveApptimizeTestInfo : NSObject
46+
47+
@property (nonatomic, strong, readonly) NSString *testName;
48+
@property (nonatomic, strong, readonly) NSString *enrolledVariantName;
49+
@property (nonatomic, strong, readonly) NSString *testID;
50+
@property (nonatomic, strong, readonly) NSNumber *enrolledVariantID;
51+
@property (nonatomic, strong, readonly) NSDate *testStartedDate;
52+
@property (nonatomic, strong, readonly) NSDate *testEnrolledDate;
53+
@property (nonatomic, strong, readonly) NSNumber *cycle;
54+
@property (nonatomic, strong, readonly) NSNumber *currentPhase;
55+
@property (nonatomic, strong, readonly) NSNumber *participationPhase;
56+
@property (nonatomic, readonly) BOOL userHasParticipated;
57+
58+
@end
59+
60+
NS_ASSUME_NONNULL_END
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
//
2+
// ApptentiveApptimize.m
3+
// Apptentive
4+
//
5+
// Created by Alex Lementuev on 5/8/18.
6+
// Copyright © 2018 Apptentive, Inc. All rights reserved.
7+
//
8+
9+
#import "ApptentiveApptimize.h"
10+
#import "ApptentiveInvocation.h"
11+
12+
NSNotificationName const ApptimizeTestsProcessedNotification = @"ApptimizeTestsProcessedNotification";
13+
NSNotificationName const ApptentiveApptimizeTestRunNotification = @"ApptimizeTestRunNotification";
14+
NSString * const ApptentiveApptimizeTestNameUserInfoKey = @"ApptimizeTestName";
15+
NSString * const ApptentiveApptimizeVariantNameUserInfoKey = @"ApptimizeVariantName";
16+
17+
static NSString * const kClassApptimize = @"Apptimize";
18+
static NSString * const kMethodTestInfo = @"testInfo";
19+
static NSString * const kMethodLibraryVersion = @"libraryVersion";
20+
21+
@interface ApptentiveApptimizeTestInfo ()
22+
23+
@property (nonatomic, strong, readwrite) NSString *testName;
24+
@property (nonatomic, strong, readwrite) NSString *enrolledVariantName;
25+
@property (nonatomic, strong, readwrite) NSString *testID;
26+
@property (nonatomic, strong, readwrite) NSNumber *enrolledVariantID;
27+
@property (nonatomic, strong, readwrite) NSDate *testStartedDate;
28+
@property (nonatomic, strong, readwrite) NSDate *testEnrolledDate;
29+
@property (nonatomic, strong, readwrite) NSNumber *cycle;
30+
@property (nonatomic, strong, readwrite) NSNumber *currentPhase;
31+
@property (nonatomic, strong, readwrite) NSNumber *participationPhase;
32+
@property (nonatomic, readwrite) BOOL userHasParticipated;
33+
34+
@end
35+
36+
@implementation ApptentiveApptimize
37+
38+
+ (BOOL)isApptimizeSDKAvailable {
39+
return [ApptentiveInvocation classAvailable:kClassApptimize];
40+
}
41+
42+
+ (nullable NSString *)libraryVersion {
43+
ApptentiveInvocation *apptimize = [ApptentiveInvocation fromClassName:kClassApptimize];
44+
if (apptimize == nil) {
45+
ApptentiveLogError(ApptentiveLogTagApptimize, @"Can't get Apptimize library version: class not found '%@'", kClassApptimize);
46+
return nil;
47+
}
48+
49+
return [apptimize invokeSelector:kMethodLibraryVersion];
50+
}
51+
52+
+ (BOOL)isSupportedLibraryVersion {
53+
NSString *libraryVersion = [self libraryVersion];
54+
if (libraryVersion == nil) {
55+
return NO;
56+
}
57+
58+
NSArray *tokens = [libraryVersion componentsSeparatedByString:@"."];
59+
if (tokens.count != 3) {
60+
return NO;
61+
}
62+
63+
NSUInteger major = [tokens[0] intValue];
64+
return major >= 3;
65+
}
66+
67+
+ (nullable NSDictionary<NSString *, ApptentiveApptimizeTestInfo *> *)testInfo {
68+
ApptentiveInvocation *apptimize = [ApptentiveInvocation fromClassName:kClassApptimize];
69+
if (apptimize == nil) {
70+
ApptentiveLogError(ApptentiveLogTagApptimize, @"Can't list experiments: class not found '%@'", kClassApptimize);
71+
return nil;
72+
}
73+
74+
NSDictionary *apptimizeTestsInfo = [apptimize invokeSelector:kMethodTestInfo];
75+
if (apptimizeTestsInfo == nil) {
76+
ApptentiveLogError(ApptentiveLogTagApptimize, @"Can't list experiments: [%@ %@] can't be resolved", kClassApptimize, kMethodTestInfo);
77+
return nil;
78+
}
79+
80+
if (![apptimizeTestsInfo isKindOfClass:[NSDictionary class]]) {
81+
ApptentiveLogError(ApptentiveLogTagApptimize, @"Can't list experiments: [%@ %@] returned unexpected result %@", kClassApptimize, kMethodTestInfo, [apptimizeTestsInfo class]);
82+
return nil;
83+
}
84+
85+
NSMutableDictionary<NSString *, ApptentiveApptimizeTestInfo *> *experiments = [NSMutableDictionary new];
86+
87+
for (NSString *experimentName in apptimizeTestsInfo) {
88+
id experimentObj = apptimizeTestsInfo[experimentName];
89+
if (experimentObj == nil) {
90+
continue;
91+
}
92+
93+
ApptentiveInvocation *experimentInvocation = [ApptentiveInvocation fromObject:experimentObj];
94+
95+
ApptentiveApptimizeTestInfo *testInfo = [ApptentiveApptimizeTestInfo new];
96+
testInfo.testName = [experimentInvocation invokeSelector:@"testName"];
97+
testInfo.enrolledVariantName = [experimentInvocation invokeSelector:@"enrolledVariantName"];
98+
testInfo.testID = [experimentInvocation invokeSelector:@"testID"];
99+
testInfo.enrolledVariantID = [experimentInvocation invokeSelector:@"enrolledVariantID"];
100+
testInfo.testStartedDate = [experimentInvocation invokeSelector:@"testStartedDate"];
101+
testInfo.testEnrolledDate = [experimentInvocation invokeSelector:@"testEnrolledDate"];
102+
testInfo.cycle = [experimentInvocation invokeSelector:@"cycle"];
103+
testInfo.currentPhase = [experimentInvocation invokeSelector:@"currentPhase"];
104+
testInfo.participationPhase = [experimentInvocation invokeSelector:@"participationPhase"];
105+
testInfo.userHasParticipated = [[experimentInvocation invokeBoolSelector:@"userHasParticipated"] boolValue];
106+
107+
experiments[experimentName] = testInfo;
108+
}
109+
110+
return experiments;
111+
}
112+
113+
@end
114+
115+
@implementation ApptentiveApptimizeTestInfo
116+
@end

Apptentive/Apptentive/Info.plist

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
<key>CFBundlePackageType</key>
1616
<string>FMWK</string>
1717
<key>CFBundleShortVersionString</key>
18-
<string>5.1.0</string>
18+
<string>5.1.1</string>
1919
<key>CFBundleVersion</key>
2020
<string>$(CURRENT_PROJECT_VERSION)</string>
2121
<key>NSPrincipalClass</key>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//
2+
// ApptentiveClass.h
3+
// Apptentive
4+
//
5+
// Created by Alex Lementuev on 5/8/18.
6+
// Copyright © 2018 Apptentive, Inc. All rights reserved.
7+
//
8+
9+
#import <Foundation/Foundation.h>
10+
11+
NS_ASSUME_NONNULL_BEGIN
12+
13+
@interface ApptentiveInvocation : NSObject
14+
15+
@property (nonatomic, strong, readonly) id target;
16+
17+
+ (BOOL)classAvailable:(NSString *)className;
18+
19+
+ (nullable instancetype)fromClassName:(NSString *)className;
20+
+ (nullable instancetype)fromObject:(id)object;
21+
22+
- (nullable id)invokeSelector:(NSString *)selectorName;
23+
- (nullable NSNumber *)invokeBoolSelector:(NSString *)selectorName;
24+
25+
@end
26+
27+
NS_ASSUME_NONNULL_END

0 commit comments

Comments
 (0)