leancloud / ChatKit-OC

此项目已经废弃,以后不再维护。我们推出了基于 Swift SDK 的 Chat Demo。
https://github.com/leancloud/swift-sdk-demo
MIT License
2.12k stars 461 forks source link

LeanCloudIMKit-iOS接口设计 #1

Closed ChenYilong closed 8 years ago

ChenYilong commented 8 years ago

IMKit 要提供的类

类前缀:LCIM。

IMKit 要提供的类 接口开放形式 关键词
LCIMChatViewController 继承 if not opened , throw exception
LCIMChatManager 直接调用 open、close、signature、initWitClientId
LCIMChatViewControllerDelegate 协议 --
LCIMProfileProviderDelegate 协议 用户系统转换
LCIMSignatureFactoryDelegate 协议 签名方法生成

另外提供一个 notification ,让用户在前台接收通知用。

Demo必须要包括的类

LCIMConversationListViewController。

LCIMChatViewController 相关接口

/*!
 *  聊天初始化所需的conversationId, 群聊需要使用该属性初始化
 *  对应的初始化方法: `-initWithConversationId:` 、`+chatWithConversationId:` 
 */
@property (nonatomic, copy, readonly) NSString *conversationId;

/*!
 *  聊天初始化所需的memberId,适用于单聊,群聊不能使用该属性初始化,
 *  对应的初始化方法: `-initWithMemberId:` 、`+chatWithMemberId` 
 */
@property (nonatomic, copy, readonly) NSString *memberId;

- (instancetype)initWithConversationId:(NSString *)conversationId;

+ (instancetype)chatWithConversationId:(NSString *)conversationId;

- (instancetype)initWithMemberId:(NSString *)memberId;

+ (instancetype)chatWithMemberId:(NSString *)memberId;

通过点击用户头像进入用户 profile 页面;

- (void)didSelectAvatarOnMessage:(id<LCIMMessageModel>)message indexPath:(NSIndexPath *)indexPath;
- (void)didSelectMember:(id<LCIMUserDelegate>)member;

LCIMUserDelegate


@property (nonatomic, copy) NSString *userId;
@property (nonatomic, strong) UIImage *avatar;
@property (nonatomic, copy) NSString *avatarURL;

LCIMProfileProviderDelegate

用户体系转换:

currentUser 相关的信息也通过该接口获得:

@required

//typedef void (^LCIMResultCallBack)(NSArray *users, NSError *error)
- (void)getProfilesWithUserIds:(NSArray *) userIds callback:(LCIMCallBack)callback;

LCIMChatManager

@property (nonatomic, weak) id<LCIMProfileProviderDelegate> profileProviderDelegate;
@property (nonatomic, weak) id<LCIMSignatureFactoryDelegate> signatureFactoryDelegate;

- (instancetype)initWithAppId:(NSString *)appId appKey:(NSString *)appKey;
- (void)openWithClientId:(NSString *)clientId callback:(LCIMBoolCallBack)callback;
- (void)close:(LCIMBoolCallBack)callback;

@leancloud/objective-c

reference : https://github.com/leancloud/paas/issues/816

wrshi commented 8 years ago

我觉得可以啦。

tang3w commented 8 years ago

使用统一的 LC 名字前缀是否合适?

+[ChatViewController chatWithConversationId:currentUser:] 感觉多余,而且「chat」不符合 Objective-C 的命名规范。

Delegate 方法需不需要加上前缀,或者增加 chatViewController:profileProvider: 参数?在命名冲突的情况下,这个参数可能会有用。

jwfing commented 8 years ago

有几个问题:

jwfing commented 8 years ago
  • (void)getProfiles:(LCIMCallBack)callback

这个函数声明该怎么实现和被调用没有看懂,如果你要实现一个基于 LeanCloud 帐户系统的 profileProvider,该怎么写代码?

wrshi commented 8 years ago

@jwfing

-- LCIMProfileProviderDelegate 这个类里面,如何提供 currentUser 的相关信息?在 Android 那边,currentUser 是保存在 ChatManager 里面的(因为 ChatManager 提供了 open/close 方法)。 怎么提供User相关信息关键就是拿到userId。这里ChatManager的open方法是用户调用的,open方法传入了一个userId,也就是说,用户是知道currentUser的userId的,那么他也就自然可以根据这个userId调用- getProfilesWithUserIds:callback:拿到当前用户信息。

-- LCIMChatViewControllerDelegate 这个的定义在哪里?是否是「通过点击用户头像进入用户 profile 页面」? 对的,当前的协议定义里就只包含这两个事件的处理方法。

-- LCIMUserDelegate 这个类名叫 Delegate 有点奇怪,只是一个 Bean,没有任何方法需要实现,和 AVUser 差不多。 这里采用delegate的想法是设置了三个用户必须提供的三个user属性。当然用户还可以提供更多的属性,只是这三个是@required。如果采用继承,用户同样可以提供更多的属性,只是这三个父类属性有为空的风险,所以还是采用了delegate(不知道这个想法对不对?)。

-- LCIMChatViewController 在 viewDidAppeared 中如果聊天服务未 open,那么抛出 exception 不太好,这会增加这个 lib crash 的几率,更好的做法是提示用户,然后什么都不干,只能让用户返回。 昨天宜龙说这个exception是提示给开发者的不是提示给用户的,因为Kit是给开发者用的...如果开发者没有正确调用open,就属于fatal error需要以exception来提示他。我觉得好像也蛮有道理的...

-(void)getProfiles:(LCIMCallBack)callback 这个函数声明该怎么实现和被调用没有看懂,如果你要实现一个基于 LeanCloud 帐户系统的 profileProvider,该怎么写代码? 这里没写全啊还是后来函数名改了?现在是这样:- (void)getProfilesWithUserIds:(NSArray *) userIds callback:(LCIMCallBack)callback; 写一个基于LeanCloud账户系统的代码的话,恩感觉大概是这样吧不知道对不对:

- (void)getProfilesWithUserIds:(NSArray *)userIds callback:(LCIMCallBack)callback {
    NSMutableArray<id<LCIMUserDelegate>> *userList = [NSMutableArray array];
    for (NSString *userId in userIds) {
        AVQuery *query = [AVUser query];
        [query getObjectInBackgroundWithId:userId block:^(AVObject *object, NSError *error) {
            if (error == nil) {
                [userList addObject:object];
            } else {
                if (callback) {
                    callback(nil, error);
                }
            }
        }];
    }
    if (callback) {
        callback(userList, nil);
    }
}
ChenYilong commented 8 years ago

@leancloud/objective-c @daweibayu

chat 换成 conversation 是不是更规范一些?

ChatViewController --》ConversationViewController ChatManager ---》ConversationManager

wrshi commented 8 years ago

@ChenYilong

嗯我的理解是...chat = informal conversation,就是说在这里使用上并不存在是否规范的问题,只有这个场景更适合哪个名词的问题。我个人还是倾向于chat,因为IM这种场景本身就是比较随意的,聊天对象一般是朋友。conversation就比较正式了,是那种“我要跟你谈一谈”的感觉...另外很多聊天应用都用chat这个词,比如snapchat。

jwfing commented 8 years ago

@ChenYilong 我觉得 @tang3w 提到 +[ChatViewController chatWithConversationId:currentUser:]chat 不符合命名规范,是指 oc 里面一般是叫成 [Class instanceWithParameter:] 这样的吧。

wrshi commented 8 years ago

对。。写出ChatViewControllerWithConversationId:currentUser: 好了。就是长了点(:з」∠)

jwfing commented 8 years ago

@wrshi

怎么提供User相关信息关键就是拿到userId。这里ChatManager的open方法是用户调用的,open方法传入了一个userId,也就是说,用户是知道currentUser的userId的,那么他也就自然可以根据这个userId调用- getProfilesWithUserIds:callback:拿到当前用户信息。

其实获取 currentUser 信息与这个接口是没有关系的,没有必要在这里单独说明。

(void)getProfiles:(LCIMCallBack)callback 这个函数声明该怎么实现和被调用没有看懂,如果你要实现一个基于 LeanCloud 帐户系统的 profileProvider,该怎么写代码

这个函数声明之前是错误的,我提问是想让你们改过来,你回答的时候 @ChenYilong 已经改了,所以。。。

昨天宜龙说这个exception是提示给开发者的不是提示给用户的,因为Kit是给开发者用的...如果开发者没有正确调用open,就属于fatal error需要以exception来提示他。我觉得好像也蛮有道理的。

oc 语法上不像 Java 有强制的 Exception 静态检查,异常都是在运行时抛出来的,开发者从接口定义上可能不知道会抛出异常,所以代码中就不会处理,会直接导致 app crash。这也是我们 SDK 里面不用异常的原因。

tang3w commented 8 years ago

嗯,是这个意思。可能使用 +[LCIMChatViewController chatViewControllerWithParameter:] 可能会更合适。我觉得没必要加这个静态方法,冗余。Objective-C 的样子本来就很胖,遵循它的约定会比较好。

jwfing commented 8 years ago

那个 WithParameter 我只是举个例子,我觉得 LCIMChatViewController 要提供静态的构造方法,可以命名成这样(当然,不要这两个函数也行):

+ (instancetype) instanceWithConversationId:(NSString *)conversationId;
+ (instancetype) instanceWithMemberId:(NSString *)memberId;
tang3w commented 8 years ago

Objective-C 里面不建议抛异常,不会 unwind 调用栈,有一点点性能原因,苹果官方也是不太推荐的。除非像 Swift 那样在语法层面迫使用户做异常处理。可否在界面上给出提示,把异常的描述显示出来?这样可能会更友好一点。

wrshi commented 8 years ago

@jwfing 其他的我懂啦。但是currentUser按您的意思是想设计成怎样获取呢?没有懂。。

然后异常那里还是想采用alert是吗?

“OC的样子本来就很胖”23333333333

tang3w commented 8 years ago

要不直接 label 显示得了,也比 crash 来得友好。

jwfing commented 8 years ago

@wrshi 对于 LCIMProfileProviderDelegate 这个代理,看到 currentUser 相关的信息也通过该接口获得 时我担心你们也跟 Android 那边一样,会多一个 getSelf 方法。其实我觉得这个代理里面直接列一个 - (void)getProfilesWithUserIds:(NSArray *) userIds callback:(LCIMCallBack)callback; 方法就可以了,至于 currentUser 从哪里获取,其实不用说明的(因为是 ChatViewController 里面的逻辑)。

wrshi commented 8 years ago

@jwfing 噢懂了。那就把这个说明去掉好了,没有打算加getSelf方法的。

@tang3w 用label做..how...放到哪里呀...alert不够友好吗?点取消然后返回未登录(或者未open)页面就好了。

tang3w commented 8 years ago

这个可能得问问设计师了,我也不知道。

tang3w commented 8 years ago

好奇。。IMKit 有设计师参与吗?如果没有,暂时使用 alert 也没关系。

wrshi commented 8 years ago

暂时并没有设计师。。。

jwfing commented 8 years ago

没有设计师,UI 你们就用 leanchat 的设计好了。对于未 open 的 case,先直接用 UIAlertView 吧。

jwfing commented 8 years ago

@ChenYilong 你可以把工程框架和这部分接口的代码发个 PR 上来了(不要包含任何实现代码)。有关函数声明细节在 PR 上去讨论。

ChenYilong commented 8 years ago

收到。

ChenYilong commented 8 years ago

接口已大致稳定,先关闭了。