喜欢使用 firebase crash 的反馈。快速点赞-移除点赞

Like feedback using firebase crash. Fast click like-remove like

我有一个像 instagram 这样的应用程序。它有反馈页面。

当用户喜欢某个 post 时,我会添加此赞和反馈(使用其自己的密钥 (.childByAutoId)。

static func add(_ newLike: LikeItem) {
  // add like id for user feedback implementation
  var like = newLike
  let likeRef = ref.child("/userslikes/" + newLike.userId + "/onposts/" + newLike.postId).childByAutoId()
  like.key = likeRef.key

  var updates: [String: Any?] = [
     "/userslikes/" + like.userId + "/onposts/" + like.postId: like.toAnyObject(),
     "/postslikes/" + like.postId + "/"         + like.userId: like.toAnyObject()
  ]

  if like.userId != like.postAddedByUserId { // dont add your own likes
     var likeForFeedBack = like.toAnyObject()
     likeForFeedBack["isViewed"] = false // when user will open feedback -> true
     updates.updateValue(likeForFeedBack, forKey: "/feedback/" + like.postAddedByUserId + "/" + like.key)
  }

  ref.updateChildValues(updates)
}

没关系。而且我还有 remove 功能。它将喜欢节点,从这个喜欢中获得这个喜欢和feedbackId。然后我进行多部分更新。

static func remove(with userId: String, _ post: PostItem) {
  var updates: [String: Any?] = [
     "/userslikes/" + userId   + "/onposts/" + post.key: nil,
     "/postslikes/" + post.key + "/"         + userId:   nil
  ]

  // deleting from feedback node
  getLikeFromUser(id: userId, postId: post.key) { like in
     if like.userId != like.postAddedByUserId {
        updates.updateValue(nil, forKey: "/feedback/" + like.postAddedByUserId + "/" + like.key)
     }

     ref.updateChildValues(updates)
  }
}

static func getLikeFromUser(id: String, postId: String,
                           completion: @escaping (_ likeId: LikeItem) -> Void) {
  let refToLike = ref.child("/userslikes/" + id + "/onposts/" + postId)

  refToLike.observeSingleEvent(of: .value, with: { snapshot in
     let like = LikeItem(snapshot: snapshot)

     completion(like)
  })
}

所以,当用户点击 "remove like" 时,我有一些延迟(此时正在获取类似实体以获取反馈 ID)。

还有问题:如果我在发送垃圾邮件 like-removeLike 按钮(喜欢 - 删除喜欢 - l - rl - l - rl 等),有时我的反馈节点正在复制(使用不同的键。它没有删除旧节点),有时它没有添加(在这种情况下,如果我以后尝试删除它,它会崩溃)。

如何解决?

我的愚见,首先这可以通过用户体验限制来解决。用户不应该向应用程序中的任何按钮发送垃圾邮件。必须是这些事件之间的延迟。即使你可以添加一些最大值。在用户决定之间切换...等一下,然后再次释放它(也许)。

正如您在评论中所说,等待用户完成写入操作是个好主意和良好的用户体验。这样你就可以消除糟糕的用户体验。

您可以使用 userinteractionenabled 属性 的 UIView。

When set to NO, touch, press, keyboard, and focus events intended for the view are ignored and removed from the event queue. When set to YES, events are delivered to the view normally. The default value of this property is YES.

During an animation, user interactions are temporarily disabled for all views involved in the animation, regardless of the value in this property. You can disable this behavior by specifying the UIViewAnimationOptionAllowUserInteraction option when configuring the animation.

当然还有很多选择,天空是UX场景的极限。

您还可以查看 Apple 的用户界面加载指南:

https://developer.apple.com/ios/human-interface-guidelines/interaction/loading/

Show content as soon as possible. Don’t make people wait for content to load before seeing the screen they're expecting. Show the screen immediately, and use placeholder text, graphics, or animations to identify where content isn't available yet. Replace these placeholder elements as the content loads. Whenever possible, preload upcoming content in the background, such as while an animation is playing or the user is navigating a level or menu.

指标可能是:

https://developer.apple.com/ios/human-interface-guidelines/ui-controls/progress-indicators/

If it’s helpful, provide useful information while waiting for a task to complete. Include a label above an activity indicator to give extra context. Avoid vague terms like loading or authenticating because they don’t usually add any value.

另一种选择

正如您在下面的评论中所说,还有另一种选择可以保留 like/dislike,直到用户生活在 ViewController。但是还有另一个 UX 问题,当用户尝试关闭模式或返回到以前的视图控制器时,他们将等待此后台作业完成。另一个问题是,如果用户终止了应用程序,您还剩下 1 个更改来保存数据,它是 AppDelegate 的 applicationWillTerminate。但是在那里保存数据是不好的做法,因为 5 秒限制:

https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623111-applicationwillterminate

This method lets your app know that it is about to be terminated and purged from memory entirely. You should use this method to perform any final clean-up tasks for your app, such as freeing shared resources, saving user data, and invalidating timers. Your implementation of this method has approximately five seconds to perform any tasks and return.

If the method does not return before time expires, the system may kill the process altogether. For apps that do not support background execution or are linked against iOS 3.x or earlier, this method is always called when the user quits the app. For apps that support background execution, this method is generally not called when the user quits the app because the app simply moves to the background in that case. However, this method may be called in situations where the app is running in the background (not suspended) and the system needs to terminate it for some reason. After calling this method, the app also posts a UIApplicationWillTerminate notification to give interested objects a chance to respond to the transition.

希望对您有所帮助。