[英]Application tried to present a nil modal view controller on target in React Native Objective-C extension
我正在嘗試將 iOS 應用程序移植到 React Native。
在這個 iOS 應用程序中,需要完成的功能之一是將其與 PayPal 庫(目前已棄用 - 我們希望在今年晚些時候離開它,但沒有資源做所以現在)。
我們對這個庫所做的只是從 PayPal 獲取一個唯一代碼 - 這需要一個視圖 Controller 彈出,接受客戶端憑據並返回一個代碼來授予訪問權限。
我對 Objective-C非常陌生。
到目前為止我已經得到了這個(注意:我沒有包括所有的方法/屬性,但可以包括任何缺失的):
COMPLETE PaypalSdk.h 和 PaypalSdk.m 現在位於底部
我基於這個庫:
這個文檔:
https://github.com/paypal/PayPal-iOS-SDK/blob/master/docs/profile_sharing_mobile.md
但是,當嘗試我上面的內容時,我收到以下錯誤:
我應該如何解決這個問題? 它似乎需要一個 View Controller 但我不完全確定如何在這種情況下從 React Native 啟動一個。
我們試圖獲得的只是共享的個人資料信息。
這是堆棧跟蹤之一:
callstack: (
0 CoreFoundation 0x00007fff23c7127e __exceptionPreprocess + 350
1 libobjc.A.dylib 0x00007fff513fbb20 objc_exception_throw + 48
2 UIKitCore 0x00007fff47a25b1a -[UIViewController _presentViewController:withAnimationController:completion:] + 5247
3 UIKitCore 0x00007fff47a2801b __63-[UIViewController _presentViewController:animated:completion:]_block_invoke + 98
4 UIKitCore 0x00007fff47a28533 -[UIViewController _performCoordinatedPresentOrDismiss:animated:] + 511
5 UIKitCore 0x00007fff47a27f79 -[UIViewController _presentViewController:animated:completion:] + 187
6 UIKitCore 0x00007fff47a281e0 -[UIViewController presentViewController:animated:completion:] + 150
7 myappname 0x000000010f92f8ac -[PaypalSdk getUserAuthorizationForProfileSharing] + 348
8 myappname 0x000000010f92fd99 -[PaypalSdk generateCode:] + 233
9 CoreFoundation 0x00007fff23c7820c __invoking___ + 140
10 CoreFoundation 0x00007fff23c753af -[NSInvocation invoke] + 319
11 CoreFoundation 0x00007fff23c75684 -[NSInvocation invokeWithTarget:] + 68
12 myappname 0x000000010f6e3902 -[RCTModuleMethod invokeWithBridge:module:arguments:] + 2658
13 myappname 0x000000010f6e7a37 _ZN8facebook5reactL11invokeInnerEP9RCTBridgeP13RCTModuleDatajRKN5folly7dynamicE + 791
14 myappname 0x000000010f6e7543 _ZZN8facebook5react15RCTNativeModule6invokeEjON5folly7dynamicEiENK3$_0clEv + 131
15 myappname 0x000000010f6e74b9 ___ZN8facebook5react15RCTNativeModule6invokeEjON5folly7dynamicEi_block_invoke + 25
16 libdispatch.dylib 0x0000000110caddd4 _dispatch_call_block_and_release + 12
17 libdispatch.dylib 0x0000000110caed48 _dispatch_client_callout + 8
18 libdispatch.dylib 0x0000000110cb55ef _dispatch_lane_serial_drain + 788
19 libdispatch.dylib 0x0000000110cb617f _dispatch_lane_invoke + 422
20 libdispatch.dylib 0x0000000110cc1a4e _dispatch_workloop_worker_thread + 719
21 libsystem_pthread.dylib 0x00007fff5246371b _pthread_wqthread + 290
22 libsystem_pthread.dylib 0x00007fff5246357b start_wqthread + 15
)
這是我完整的 PayPalSdk.m 文件:
#import <PayPal-iOS-SDK/PayPalMobile.h>
#import <PayPal-iOS-SDK/PayPalConfiguration.h>
#import <PayPal-iOS-SDK/PayPalOAuthScopes.h>
#import <PayPal-iOS-SDK/PayPalProfileSharingViewController.h>
#import <QuartzCore/QuartzCore.h>
#import "PaypalSdk.h"
@interface PaypalSdk ()
@property(nonatomic, strong, readwrite) IBOutlet UIButton *payNowButton;
@property(nonatomic, strong, readwrite) IBOutlet UIButton *payFutureButton;
@property(nonatomic, strong, readwrite) IBOutlet UIView *successView;
@property(nonatomic, strong, readwrite) PayPalConfiguration *payPalConfig;
@end
@implementation PaypalSdk
#define kPayPalEnvironment PayPalEnvironmentProduction
//int *REQUEST_CODE_PROFILE_SHARING = 3;
- (void)viewDidLoad {
[super viewDidLoad];
self.title = @"Pinyada PayPal";
// Set up payPalConfig
self.payPalConfig = [[PayPalConfiguration alloc] init];
self.payPalConfig.acceptCreditCards = NO;
self.payPalConfig.merchantName = @"Pinyada PayPal";
self.payPalConfig.merchantPrivacyPolicyURL = [NSURL URLWithString:@"https://www.paypal.com/webapps/mpp/ua/privacy-full"];
self.payPalConfig.merchantUserAgreementURL = [NSURL URLWithString:@"https://www.paypal.com/webapps/mpp/ua/useragreement-full"];
NSLog(@"PayPal iOS SDK version: %@", [PayPalMobile libraryVersion]);
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
#warning "Enter your credentials"
[PayPalMobile initializeWithClientIdsForEnvironments:@{PayPalEnvironmentProduction : @"PayPalProductionID",
PayPalEnvironmentSandbox : @"YOUR_CLIENT_ID_FOR_SANDBOX"}];
return YES;
}
/*- (void)generateCode:()code {
NSLog(@"Test");
}*/
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
// Start out working with the mock environment. When you are ready, switch to PayPalEnvironmentProduction.
[PayPalMobile preconnectWithEnvironment:PayPalEnvironmentProduction];
}
- (IBAction)getUserAuthorizationForProfileSharing:(id)sender {
NSSet *scopeValues = [NSSet setWithArray:@[kPayPalOAuth2ScopeOpenId, kPayPalOAuth2ScopeEmail, kPayPalOAuth2ScopeAddress, kPayPalOAuth2ScopePhone]];
PayPalProfileSharingViewController *profileSharingPaymentViewController = [[PayPalProfileSharingViewController alloc] initWithScopeValues:scopeValues configuration:self.payPalConfig delegate:self];
[self presentViewController:profileSharingPaymentViewController animated:YES completion:nil];
}
- (IBAction)obtainConsent {
// Choose whichever scope-values apply in your case. See `PayPalOAuthScopes.h` for a complete list of available scope-values.
NSSet *scopeValues = [NSSet setWithArray:@[kPayPalOAuth2ScopeOpenId, kPayPalOAuth2ScopeEmail, kPayPalOAuth2ScopeAddress, kPayPalOAuth2ScopePhone]];
PayPalProfileSharingViewController *psViewController;
NSLog(@"PS VIEW CONTROLLER");
NSLog(psViewController);
psViewController = [[PayPalProfileSharingViewController alloc] initWithScopeValues:scopeValues
configuration:self.payPalConfig
delegate:self];
// Access the root view controller
UIViewController *rootviewcontroller= [UIApplication sharedApplication].keyWindow.rootViewController;
// Present the PayPalProfileSharingViewController
[ rootviewcontroller presentViewController:psViewController animated:YES completion:nil];
}
- (void)userDidCancelPayPalProfileSharingViewController:(PayPalProfileSharingViewController *)profileSharingViewController {
// User cancelled login. Dismiss the PayPalProfileSharingViewController, breathe deeply.
[self dismissViewControllerAnimated:YES completion:nil];
}
- (void)payPalProfileSharingViewController:(PayPalProfileSharingViewController *)profileSharingViewController
userDidLogInWithAuthorization:(NSDictionary *)profileSharingAuthorization {
// The user has successfully logged into PayPal, and has consented to profile sharing.
NSLog(@"REACT NATIVE ENV test");
// Be sure to dismiss the PayPalProfileSharingViewController.
[self dismissViewControllerAnimated:YES completion:nil];
}
RCT_EXPORT_MODULE()
RCT_EXPORT_METHOD(generateCode: (RCTResponseSenderBlock)callback) {
[PayPalMobile initializeWithClientIdsForEnvironments:@{PayPalEnvironmentProduction : @"PayPalProductionID",
PayPalEnvironmentSandbox : @"YOUR_CLIENT_ID_FOR_SANDBOX"}];
[self obtainConsent];
NSLog(@"REACT NATIVE ENV test");
//code = @"this is a test!";
// TODO: Implement some actually useful functionality
callback(@[[NSNull null], @"test"]);
}
@end
這是我完整的 PaypalSdk.h 文件:
#import "RCTBridgeModule.h"
#import "PayPalMobile.h"
@interface PaypalSdk : UIViewController <RCTBridgeModule, PayPalProfileSharingDelegate>
@property(nonatomic, strong, readwrite) NSString *environment;
@property(nonatomic, strong, readwrite) NSString *resultText;
@property(nonatomic, strong) UIWindow *window;
@property(nonatomic, strong) UIViewController *rootViewController;
@end
所以你需要訪問根視圖 controller 然后調用presentViewController
。 像下面這樣的東西應該可以解決問題:
- (IBAction)obtainConsent {
// Choose whichever scope-values apply in your case. See `PayPalOAuthScopes.h` for a complete list of available scope-values.
NSSet *scopeValues = [NSSet setWithArray:@[kPayPalOAuth2ScopeOpenId, kPayPalOAuth2ScopeEmail, kPayPalOAuth2ScopeAddress, kPayPalOAuth2ScopePhone]];
PayPalProfileSharingViewController *psViewController;
psViewController = [[PayPalProfileSharingViewController alloc] initWithScopeValues:scopeValues
configuration:self.payPalConfig
delegate:self];
// Access the root view controller
UIViewController *rootviewcontroller= [UIApplication sharedApplication].keyWindow.rootViewController;
// Present the PayPalProfileSharingViewController
[ rootviewcontroller presentViewController:psViewController animated:YES completion:nil];
}
我還沒有嘗試過,所以請檢查並讓我知道這是否有效。 否則,請找到一個視圖,您可以在該視圖上展示 controller 視圖。
根據與 OP 的交互更新答案:
不要使用那個 SDK。 它非常古老且已被棄用。
如果您需要本機 SDK 來使用 PayPal 處理付款,您可以通過 Braintree 使用快速結帳。 它還需要您自己的 web 服務: https://developer.paypal.com/docs/accept-payments/express-checkout/ec-braintree-tree-getd
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.