Sinch iOS - 'NSInvalidArgumentException', '-[UIDevice reb_platform]: 无法识别的选择器

Sinch iOS - 'NSInvalidArgumentException', '-[UIDevice reb_platform]: unrecognized selector

我正在尝试使用 iOS SDK 实现 Sinch,尽管仔细阅读了文档和教程,但我还是不断收到此错误:

2015-08-01 12:29:22.804 neighborfix[55154:2577760] mainUser username - [e-mail username redacted]

2015-08-01 12:29:22.815 neighborfix[55154:2577760] -[UIDevice reb_platform]: unrecognized selector sent to instance 0x7fc113f1ed40

2015-08-01 12:29:22.827 neighborfix[55154:2577760] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIDevice reb_platform]: unrecognized selector sent to instance 0x7fc113f1ed40'

*** First throw call stack:
(

0   CoreFoundation                      0x000000010a5cac65 __exceptionPreprocess + 165


1   libobjc.A.dylib                     0x000000010a263bb7 objc_exception_throw + 45

2   CoreFoundation                      0x000000010a5d20ad -[NSObject(NSObject) doesNotRecognizeSelector:] + 205

3   CoreFoundation                      0x000000010a52813c ___forwarding___ + 988

4   CoreFoundation                      0x000000010a527cd8 _CF_forwarding_prep_0 + 120

5   neighborfix                         0x000000010824fa69 SINUILocalNotificationWithSinchNotification + 13102

6   neighborfix                         0x0000000108234817 _ZN6rebrtc13OfflineInvite6encodeERKS0_PhmPm + 4432013

7   neighborfix                         0x000000010822f440 _ZN6rebrtc13OfflineInvite6encodeERKS0_PhmPm + 4410550

8   neighborfix                         0x0000000108241c79 SINCallOrderByStartTimeComparator + 43762

9   neighborfix                         0x00000001082418a0 SINCallOrderByStartTimeComparator + 42777

10  neighborfix                         0x0000000107d6ef24 -[AppDelegate sinchClientWithUserId:] + 116

11  neighborfix                         0x0000000107d7c31e -[MessagingViewController viewDidLoad] + 574

12  UIKit                               0x000000010abbe210 -[UIViewController loadViewIfRequired] + 738

13  UIKit                               0x000000010abbe40e -[UIViewController view] + 27

14  UIKit                               0x000000010b14b48d -[_UIFullscreenPresentationController _setPresentedViewController:] + 65

15  UIKit                               0x000000010ab98da9 -[UIPresentationController initWithPresentedViewController:presentingViewController:] + 105

16  UIKit                               0x000000010abca288 -[UIViewController _presentViewController:withAnimationController:completion:] + 1761

17  UIKit                               0x000000010abcc701 __62-[UIViewController presentViewController:animated:completion:]_block_invoke + 132

18  UIKit                               0x000000010abcc625 -[UIViewController presentViewController:animated:completion:] + 229

19  neighborfix                         0x0000000107da73e6 -[FixerRequestController submitPressed:] + 230

20  UIKit                               0x000000010aa8eda2 -[UIApplication sendAction:to:from:forEvent:] + 75

21  UIKit                               0x000000010aa8eda2 -[UIApplication sendAction:to:from:forEvent:] + 75

22  UIKit                               0x000000010aba054a -[UIControl _sendActionsForEvents:withEvent:] + 467

23  UIKit                               0x000000010ab9f919 -[UIControl touchesEnded:withEvent:] + 522

24  UIKit                               0x000000010aadb998 -[UIWindow _sendTouchesForEvent:] + 735

25  UIKit                               0x000000010aadc2c2 -[UIWindow sendEvent:] + 682

26  UIKit                               0x000000010aaa2581 -[UIApplication sendEvent:] + 246

27  UIKit                               0x000000010aaafd1c _UIApplicationHandleEventFromQueueEvent + 18265

28  UIKit                               0x000000010aa8a5dc _UIApplicationHandleEventQueue + 2066

29  CoreFoundation                      0x000000010a4fe431 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17

30  CoreFoundation                      0x000000010a4f42fd __CFRunLoopDoSources0 + 269

31  CoreFoundation                      0x000000010a4f3934 __CFRunLoopRun + 868

32  CoreFoundation                      0x000000010a4f3366 CFRunLoopRunSpecific + 470

33  GraphicsServices                    0x000000010bea4a3e GSEventRunModal + 161

34  UIKit                               0x000000010aa8d900 UIApplicationMain + 1282

35  neighborfix                         0x0000000107d7d6df main + 111

36  libdyld.dylib                       0x000000010f456145 start + 1
)

libc++abi.dylib: terminating with uncaught exception of type NSException

我试过以下方法:

  1. 删除了 Sinch 框架并重新安装了最新版本 (3.5.2)。我确保删除后我从文件目录中删除了,并且在重新安装并确保它被复制之前,General 中的 "Linked Frameworks and Libraries" 和 Build Phases 中的 "Link Binary With Libraries" 中的所有引用都没有引用 Sinch。我已经加载了所有必需的框架[包括那些用于 Parse 冲突的框架](AVFoundation、Security、Audiotoolbox、Bolts、libstc++6.0.9.dylib)和所有必需的链接器标志(-ObjC、-Xlinker、-lc++)。

  2. 仔细检查正确的 Sinch 委托实现(SINClientDelegate、SINMessageClientDelegate)并将整个 Sinch 委托 setup/implementation 移动到 AppDelegate 以使其更易于分析。

  3. 已在实际设备和模拟器上尝试运行

  4. 更改了 Sinch 应用程序设置,因此我的应用程序不需要 JS 身份验证(尽管我认为这不会影响 iOS SDK)。

  5. 在整个项目中搜索了对 reb_platform 的任何引用,并找到了 none。这可能是 Sinch 私有方法在其库中进行的调用。

这是我的相关代码:

AppDelegate.h:

#import <UIKit/UIKit.h>
#import <Sinch/Sinch.h>

@interface AppDelegate : UIResponder <UIApplicationDelegate, SINClientDelegate, SINMessageClientDelegate>

@property (strong, nonatomic) UIWindow *window;
@property (strong, nonatomic) id<SINClient> client;
@property (strong, nonatomic) id<SINMessageClient>sinchMessageClient;

- (void)sinchClientWithUserId:(NSString *)userId;
-(void)sendMessage:(NSString *)messageText toRecipient:(NSString *)recipientId;

@end

AppDelegate.m:

#import "AppDelegate.h"
#import <Parse/Parse.h>
#import <ParseUI/ParseUI.h>
#import <Fabric/Fabric.h>
#import <Crashlytics/Crashlytics.h>
#import "Config.h"




@interface AppDelegate ()

@end

@implementation AppDelegate


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.

    [Parse enableLocalDatastore];

    // Initialize Parse
    [Parse setApplicationId:[APPID]
                  clientKey:[CLIENT-KEY]];

    // rack statistics around application opens.
    [PFAnalytics trackAppOpenedWithLaunchOptions:launchOptions];
    [UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleLightContent;
    [PFImageView class];

    [[UIBarButtonItem appearanceWhenContainedIn: [UISearchBar class], nil] setTintColor:[UIColor whiteColor]];
    //[Fabric with:@[CrashlyticsKit]];


    return YES;
}



#pragma mark - Sinch
- (void)sinchClientWithUserId:(NSString *)userId
{

        self.client = [Sinch clientWithApplicationKey: [SINCHAPPKEY]
                                applicationSecret:[SINCHAPPSECRET]
                                  environmentHost:@"sandbox.sinch.com"
                                           userId:userId];
        self.client.delegate = self;

        [self.client setSupportCalling:NO];
        [self.client setSupportMessaging:YES];
        [self.client start];
        [self.client startListeningOnActiveConnection];

}

- (void)clientDidStart:(id<SINClient>)client
{
    NSLog(@"Sinch client started successfully (version: %@)", [Sinch version]);
    self.sinchMessageClient = [self.client messageClient];
    self.sinchMessageClient.delegate =  self;
}

- (void)clientDidFail:(id<SINClient>)client error:(NSError *)error
{
    NSLog(@"Sinch client error: %@", [error localizedDescription]);
}

- (void)client:(id<SINClient>)client logMessage:(NSString *)message area:(NSString *)area severity:(SINLogSeverity)severity timestamp:(NSDate *)timestamp
{
    if (severity == SINLogSeverityCritical)
    {
        NSLog(@"%@", message);
    }
}

#pragma mark SINMessageClientDelegate methods
// Receiving an incoming message.
- (void)messageClient:(id<SINMessageClient>)messageClient didReceiveIncomingMessage:(id<SINMessage>)message {
    [[NSNotificationCenter defaultCenter] postNotificationName:SINCH_MESSAGE_RECEIVED object:self userInfo:@{@"message" : message}];
}

// Finish sending a message
- (void)messageSent:(id<SINMessage>)message recipientId:(NSString *)recipientId {
    [[NSNotificationCenter defaultCenter] postNotificationName:SINCH_MESSAGE_SENT object:self userInfo:@{@"message" : message}];
}

// Failed to send a message
- (void)messageFailed:(id<SINMessage>)message info:(id<SINMessageFailureInfo>)messageFailureInfo {
    [[NSNotificationCenter defaultCenter] postNotificationName:SINCH_MESSAGE_FAILED object:self userInfo:@{@"message" : message}];
    NSLog(@"MessageBoard: message to %@ failed. Description: %@. Reason: %@.", messageFailureInfo.recipientId, messageFailureInfo.error.localizedDescription, messageFailureInfo.error.localizedFailureReason);
}

-(void)messageDelivered:(id<SINMessageDeliveryInfo>)info
{
    [[NSNotificationCenter defaultCenter] postNotificationName:SINCH_MESSAGE_SENT object:info];
}



-(void)sendMessage:(NSString *)messageText toRecipient:(NSString *)recipientId{

    SINOutgoingMessage *message = [SINOutgoingMessage messageWithRecipient:recipientId text:messageText];
    [[self.client messageClient]sendMessage:message];


}

@end

MessagingViewController.h:

#import <UIKit/UIKit.h>
#import <Parse/Parse.h>
#import <Sinch/Sinch.h>

@interface MessagingViewController : UIViewController
@property (strong, nonatomic) PFUser *selectedUser;
@end

MessagingViewController.m:

#import "MessagingViewController.h"
#import "UsersTableViewCell.h"
#import "RecipientTableViewCell.h"
#import "TextInsetLabel.h"
#import <Sinch/Sinch.h>
#import "AppDelegate.h"
#import "Config.h"


typedef NS_ENUM(int, MessageDirection)
{
    Incoming,
    Outgoing
};

@interface MessagingViewController () <UITableViewDataSource, UITableViewDelegate, UITextFieldDelegate>
@property (strong, nonatomic) NSMutableArray *messages;
@property (weak, nonatomic) IBOutlet UITableView *tableView;
@property (weak, nonatomic) IBOutlet UITextField *messageTextField;
@property (weak, nonatomic) IBOutlet UIButton *btnSendMessage;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *messagingBottomConstraint;
@end

static NSString * CELL_ID_RECIPIENT = @"RecipientCell";
static NSString * CELL_ID_USER = @"UserCell";

@implementation MessagingViewController{

    AppDelegate *delegate;
}

#pragma mark - View Lifecycle

-(void)viewWillAppear:(BOOL)animated{

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(messageDelivered:) name:SINCH_MESSAGE_RECEIVED object:nil];

}
- (void)viewDidLoad
{
    [super viewDidLoad];
    //NSLog(@"selectedUser in Messaging - %@",self.selectedUser);

    //Init our array to hold chat messages
    self.messages = [NSMutableArray new];

    //Tableview Setup
    self.tableView.rowHeight = UITableViewAutomaticDimension;
    self.tableView.estimatedRowHeight = 66.0f;

    //Textfield Setup
    [self textFieldSetup];

    //Setup Sinch message client
    PFUser *mainUser = [PFUser currentUser];
    NSLog(@"mainUser username - %@",mainUser[@"username"]);
    delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
    [delegate sinchClientWithUserId:mainUser[@"username"]];



}

#pragma mark - Textfield Delegate & Helpers
- (void)textFieldSetup
{
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillShow:)
                                                 name:UIKeyboardWillShowNotification
                                               object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillBeHidden:)
                                                 name:UIKeyboardWillHideNotification
                                               object:nil];

    UITapGestureRecognizer *tap;
    tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)];
    [self.view addGestureRecognizer:tap];
}

- (void)keyboardWillShow:(NSNotification *)note
{
    CGRect keyboardFrameEnd = [[[note userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
    self.messagingBottomConstraint.constant = keyboardFrameEnd.size.height - 24;//Was 48

    [UIView animateWithDuration:0.25 animations:^{
        [self.view layoutIfNeeded];
    }];

    [self scrollToBottom];
}

- (void)keyboardWillBeHidden:(NSNotification *)note
{
    self.messagingBottomConstraint.constant = 0;

    [UIView animateWithDuration:0.25 animations:^{
        [self.view layoutIfNeeded];
    }];

}

- (void)dismissKeyboard
{
    [self.messageTextField resignFirstResponder];
    [self scrollToBottom];
}

- (void)scrollToBottom
{
    //Scroll to bottom
    if (self.messages.count > 0)
    {
        NSIndexPath *indexPath = [NSIndexPath indexPathForRow:self.messages.count - 1 inSection:0];
        [self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
    }
}

#pragma mark - Table View Datasource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    //return self.messages.count;
    NSLog(@"self.messages array - %@",self.messages);
    return [self.messages count];
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [UITableViewCell new];
    id<SINMessage> message = [self.messages[indexPath.row] firstObject];
    MessageDirection direction = (MessageDirection)[[self.messages[indexPath.row] lastObject] intValue];

    if (direction == Incoming)
    {
        cell = [self.tableView dequeueReusableCellWithIdentifier:CELL_ID_RECIPIENT];
        ((RecipientTableViewCell *)cell).message.text = message.text;
    }
    else
    {
        cell = [self.tableView dequeueReusableCellWithIdentifier:CELL_ID_USER];
        ((UsersTableViewCell *)cell).message.text = message.text;
    }
    return cell;
}

#pragma mark - Sending Message
- (IBAction)sendMessage:(id)sender
{
    [self dismissKeyboard];
    NSLog(@"username of recipient - %@",self.selectedUser[@"username"]);

    NSString *outgoingMessage = self.messageTextField.text;
    [delegate sendMessage:outgoingMessage toRecipient:self.selectedUser[@"username"]];


}

- (void)messageDelivered:(NSNotification *)notification
{
    NSString *chatMessage = [[notification userInfo] objectForKey:@"message"];
    [self.messages addObject:chatMessage];
    [self.tableView reloadData];
    [self scrollToBottom];
}

@end

显然 MessagingViewController.m 中的这一行调用了错误:

[delegate sinchClientWithUserId:mainUser[@"username"]];

在 AppDelegate 中调用此方法:

- (void)sinchClientWithUserId:(NSString *)userId
{

        self.client = [Sinch clientWithApplicationKey: [SINCHAPPKEY]
                                applicationSecret:[SINCHAPPSECRET]
                                  environmentHost:@"sandbox.sinch.com"
                                           userId:userId];
        self.client.delegate = self;

        [self.client setSupportCalling:NO];
        [self.client setSupportMessaging:YES];
        [self.client start];
        [self.client startListeningOnActiveConnection];

}

一些相关的要点:

  1. Xcode6.3.2,iOS7.0+

  2. 使用 Parse 并使用为用户存储的电子邮件用户名作为 Sinch 的用户名

  3. 使用Crashlytics/Fabric

  4. 我显示在 Sinch 仪表板上没有创建用户。

感谢任何帮助。 Sinch 看起来是一个非常强大的工具,但我似乎无法使用它。谢谢。

我终于通过删除 Parse FB 实用程序并使用 -all_load 链接器标志解决了这个问题。 Sinch 客户端现在启动并且错误不再出现。我不确定是什么导致了错误,但似乎与 Sinch 和 Parse FB Utils 有一些冲突。我已经按照 Sinch 的说明加载额外的库和框架来解决任何此类冲突,但显然这还不够。