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
我试过以下方法:
删除了 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++)。
仔细检查正确的 Sinch 委托实现(SINClientDelegate、SINMessageClientDelegate)并将整个 Sinch 委托 setup/implementation 移动到 AppDelegate 以使其更易于分析。
已在实际设备和模拟器上尝试运行
更改了 Sinch 应用程序设置,因此我的应用程序不需要 JS 身份验证(尽管我认为这不会影响 iOS SDK)。
在整个项目中搜索了对 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];
}
一些相关的要点:
Xcode6.3.2,iOS7.0+
使用 Parse 并使用为用户存储的电子邮件用户名作为 Sinch 的用户名
使用Crashlytics/Fabric
我显示在 Sinch 仪表板上没有创建用户。
感谢任何帮助。 Sinch 看起来是一个非常强大的工具,但我似乎无法使用它。谢谢。
我终于通过删除 Parse FB 实用程序并使用 -all_load 链接器标志解决了这个问题。 Sinch 客户端现在启动并且错误不再出现。我不确定是什么导致了错误,但似乎与 Sinch 和 Parse FB Utils 有一些冲突。我已经按照 Sinch 的说明加载额外的库和框架来解决任何此类冲突,但显然这还不够。
我正在尝试使用 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
我试过以下方法:
删除了 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++)。
仔细检查正确的 Sinch 委托实现(SINClientDelegate、SINMessageClientDelegate)并将整个 Sinch 委托 setup/implementation 移动到 AppDelegate 以使其更易于分析。
已在实际设备和模拟器上尝试运行
更改了 Sinch 应用程序设置,因此我的应用程序不需要 JS 身份验证(尽管我认为这不会影响 iOS SDK)。
在整个项目中搜索了对 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];
}
一些相关的要点:
Xcode6.3.2,iOS7.0+
使用 Parse 并使用为用户存储的电子邮件用户名作为 Sinch 的用户名
使用Crashlytics/Fabric
我显示在 Sinch 仪表板上没有创建用户。
感谢任何帮助。 Sinch 看起来是一个非常强大的工具,但我似乎无法使用它。谢谢。
我终于通过删除 Parse FB 实用程序并使用 -all_load 链接器标志解决了这个问题。 Sinch 客户端现在启动并且错误不再出现。我不确定是什么导致了错误,但似乎与 Sinch 和 Parse FB Utils 有一些冲突。我已经按照 Sinch 的说明加载额外的库和框架来解决任何此类冲突,但显然这还不够。