JSQMessagesViewController animated typing indicator - jsqmessagesviewcontroller

I'm working on a project that uses the JSQMessagesViewController library. Has anyone successfully animated the typing indicator, and if so could they share their approach?
Thanks!

I'm late for the party but because this also take me a lot of time and my post could help others so I will list my working solution.
I use an APNG (animated PNG, which could have transparent background) as typing indicator so I use APNGKit which provide an UIImageView subclass named APNGImageView
Copy JSQMessagesTypingIndicatorFooterView.xib from Pods/Pods/JSQMessagesViewController/Resources to your source folder, rename it to MyMessagesTypingIndicatorFooterView.xib (for example)
Create a class named MyMessagesTypingIndicatorFooterView like so:
class MyMessagesTypingIndicatorFooterView: JSQMessagesTypingIndicatorFooterView {
#IBOutlet weak var animatedImageView: APNGImageView!
override func draw(_ rect: CGRect) {
super.draw(rect)
}
override func awakeFromNib() {
super.awakeFromNib();
}
public override class func nib() -> UINib! {
return UINib(nibName: "MyMessagesTypingIndicatorFooterView", bundle: Bundle.main)
}
override class func footerReuseIdentifier()->String{
return "MyMessagesTypingIndicatorFooterView"
}
}
Add APNGImageView instance to MyMessagesTypingIndicatorFooterView.xib, reference custom class MyMessagesTypingIndicatorFooterView. Add reference outlet animatedImageView to MyMessagesTypingIndicatorFooterView class.
Register custom footer in subclass of JSQMessagesViewController and override viewForSupplementaryElementOfKind
class MyMessagesViewController: JSQMessagesViewController{
override func viewDidLoad() {
self.collectionView.register(MyMessagesTypingIndicatorFooterView.nib(),
forSupplementaryViewOfKind: UICollectionElementKindSectionFooter,
withReuseIdentifier: "MyMessagesTypingIndicatorFooterView")}
override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
if kind == UICollectionElementKindSectionFooter{
let footerView = collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionElementKindSectionFooter, withReuseIdentifier: "MyMessagesTypingIndicatorFooterView", for: indexPath) as! MyMessagesTypingIndicatorFooterView
//footerView
let image = APNGImage(named: "typing1.png")
footerView.animatedImageView.image = image
footerView.animatedImageView.startAnimating()
return footerView
}
return super.collectionView(collectionView, viewForSupplementaryElementOfKind: kind, at: indexPath)
}
}

You will want to look into the JSQTypingIndicatorFooterView here is the documentation. http://cocoadocs.org/docsets/JSQMessagesViewController/7.2.0/Classes/JSQMessagesTypingIndicatorFooterView.html
You can set the ellipsisColor
messageBubbleColor the color of the bubble it self.
shouldDisplayOnLeft to decide if it should be on the left or right.
collectionView the collection view it should show on.

Related

View based NSTableView: Empty/white labels on dragging

I setup a trivial view based NSTableView, the view is a simple NSTextField used as a label:
func tableView(_ tv: NSTableView, viewFor tc: NSTableColumn?, row: Int)
-> NSView?
{
let v = (tv.makeView(withIdentifier: viewID, owner: nil) as? NSTextField)
?? NSTextField()
v.isSelectable = false
v.isEditable = false
v.stringValue = data[row] // [String]
v.identifier = viewID
return v
}
and then I enable dragging of the items using this delegate method:
func tableView(_ tableView: NSTableView, pasteboardWriterForRow row: Int)
-> NSPasteboardWriting?
{
return MyPasteboardItem(value: data[row])
}
This works, but when I drag the row, I get an empty representation of the textfield:
(in a different setup things like image views and buttons get drawn, but the NSTextField also ends up white).
I highly suspect this is due to the NSTextField being backed by a TextLayer which doesn't get drawn if the tableview captures an image of the view hierarchy being dragged.
What is a good way to fix this? I considered implementing draw(), but well.
Update: If I do an own NSTextField subclass and override draw(), it indeed starts to work:
final class MyTextField : NSTextField {
override func draw(_ dirtyRect: NSRect) {
super.draw(dirtyRect)
}
}
Looking at the thing in the view debugger shows that the Layer switches from NSTextLayer to _NSViewBackingLayer when draw is overridden.
But I assume this is not exactly desirable? Is there a better way to accomplish this?
Complete sample: https://gist.github.com/helje5/48728983951ab3362af43b967c554475
Setting drawsBackground=false on the textfield fixed it for me.
If you are using xib file then untick "Draws Background" on the Text Field or in your viewFor: method something like:
v.drawsBackground = false;
I ended up with this in an NSTextField subclass, not sure whether it is a good idea:
override public func draw(_ dirtyRect: NSRect) {
// This switches from the UXLabel being backed by `NSTextLayer` to
// `_NSViewBackingLayer`, which may not be desirable.
// BUT: This enables proper drawing of the Drag&Drop cell.
super.draw(dirtyRect)
}

Redundant conformance of TableView to protocol UITableViewDataSource with Xib Files

I have a parent view UIViewController (on storyboard), a TableViewController with .xib and TableViewCell with .xib. I am trying to connect DataSource to the TableView however it's giving me an error:
Redundant conformance of 'TableView1' to protocol 'UITableViewDataSource'
'TableView1' inherits conformance to protocol 'UITableViewDataSource' from superclass here.
Without adding dataSource near class and try it as class TableView1: UITableViewController {.. , it doesn't give me any error and in the simulator, I can see the table view illusion when I scroll down.
However, when I try to add dataSource, it gave me these errors.
The path I followed on setting it up...:
Ctrl + drag from xib to TableView1 and connected it as Globals
In xib file, I connected DataSource & Delegate
Finally, my TableView1:
class TableView1: UITableViewController, UITableViewDataSource { error here..
#IBOutlet var GlobalsTableView: UITableView!
var results: [AnyObject]? = []
override func viewDidLoad() {
super.viewDidLoad()
print("A")
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return self.results?.count ?? 0
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell") as! DogTableViewCell
return cell
}
}
Please note that in TableView1.xib, I can't select TableView1 as Custom Class -> Class (but i don't think it's necessary).
When a class inherits from UITableViewController, it by default conforms to UITableViewDataSource & UITableViewDelegate and you need not explicitly specify it.
You need to conform to UITableViewDataSource and UITableViewDelegate only when you embed a UITableView in a UIViewController.
There are at least 2 conformations in your class. You need to extend only once.
First Scenario:
You conform in the class description AND in the extension.
class MyViewController: MyDelegate{
//class functions here
}
extension MyViewController: MyDelegate{
func1()
}
Remove "My Delegate" in the class description.
class MyViewController{
//class functions here
}
extension MyViewController: MyDelegate{
func1()
}
Second Scenario:
You conform in two extensions.
extension MyViewController: MyDelegate{
func1()
}
extension MyViewController: MyDelegate{
func2()
}
Merge them into one extension like:
extension MyViewController: MyDelegate{
func1()
func2()
}

Passing an image when taped on uicollectionview to a detail view controller in swift

Ive been at this for a while but cant seem to crack it in swift
I want a user to be able to select an image in uicollectionView and for that image to appear in a detailed view controller, i can do this quite easily with a peice of text,
and i can do this when there is a static array of images preloaded. but i cant seem to get anywhere with a collectionview which is loaded with images from a camera.
I understand i need to use
override func performSegueWithIdentifier(identifier: String, sender: AnyObject?) {
}
and this function to isolated selected cell.
func collectionView(collectionView: UICollectionView, didDeselectItemAtIndexPath indexPath: NSIndexPath) {
}
I do have these outlets
#IBOutlet weak var collectionView: UICollectionView!
var images = [UIImage]()
image picker stores all images to this array by
images.insert(newImage, atIndex: 0)
when the array would be passed to the detailviewcontroller, i understand that would have to be copied into another local array and then how would i get the current image that was highlighted to be shown first, perhaps using indexPath.Row
Regards
I'm not using segues, and actually I don't quite understand what your problem is, but I'll try to show you how it could be achieved.
First of all, you have an array with images, so I believe your image should be accessed as images[indexPath.row]
let's suppose that you already have UIViewController class with UIImageView in it.
if so, you can write something like that:
func collectionView(collectionView: UICollectionView, didDeselectItemAtIndexPath indexPath: NSIndexPath) {
let myVC = MyViewController()
myVC.imageView.image = images[indexPath.row]
self.presentViewController(myVC, animated: true, completion: nil)
}
for modal or
func collectionView(collectionView: UICollectionView, didDeselectItemAtIndexPath indexPath: NSIndexPath) {
let myVC = MyViewController()
myVC.imageView.image = images[indexPath.row]
self.navigationController?.pushViewController(myVC, animated: true)
}
if you want to show it as navigational.
I believe that with segues it's basically the same but I think you have to use func prepareForSegue for, you know, preparing the segue (func performSegueWithIdentifier will just perform it). In prepareForSegue you should check identifier of your segue
if segue.identifier == "myIdentifier" {
//your code here
}
and if this identifier is right, put your commands to your myVC there.

Xcode 7 - Cell content not displayed into an empty label

I'm trying to display a cell content into an empty UILabel, but after I upgraded to Xcode 7, the content didn't show up. I was following the same mechanism and it worked on Xcode 6, but since I'm new to Swift I may have something wrong in the code.
TableViewController:
import UIKit
class TableViewController: UITableViewController {
struct dataModel {
var name:String
var val:Double
}
let foods = [dataModel(name: "name1", val: 3.3),
dataModel(name: "name2", val: 5.5)]
#IBOutlet var table: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return foods.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath)
// Configure the cell...
let foodCell = foods[indexPath.row]
cell.textLabel?.text = foodCell.name
return cell
}
var valueToPass:String!
var valueInt:Int!
override func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
let indexPath = tableView.indexPathForSelectedRow;
let currentCell = tableView.cellForRowAtIndexPath(indexPath!) as UITableViewCell!;
valueToPass = currentCell.textLabel!.text
performSegueWithIdentifier("showCalc", sender: self)
func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "showCalc") {
let viewController = segue.destinationViewController as! calcViewController
viewController.passedValue = valueToPass
}
}
}
ViewController where I want to display the tapped cell into an empty label:
import UIKit
class calcViewController: UIViewController {
#IBOutlet var text: UILabel!
#IBOutlet var empty1: UILabel!
var passedValue:String!
override func viewWillAppear(animated: Bool) {
empty1.text = passedValue
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
As a result, there is no error, but there is nothing displayed inside the empty label.
The other thing I want to achieve is to display the Int value into another label and then do some calculations, but this would be another question. Thanks in advance!
There are several issues in this code. First you are obviously missing some closing braces. But I assume this is a copy-paste error.
Why do you use didDeselectRowAtIndexPath? Don't you have a segue from the table view cell to the next controller? Then you should get the text label in prepareForSegue by using tableView.indexPathForSelectedRow.
If you like to keep it this way you should use didSelect... in stead of didDeselect....
You should take the value you want to pass to the next view controller direct from the data and not from the cell. You have the data you present in the table in the foods array.
Class names should always start with a capital letter. ALWAYS!
Having the data model within the controller is poor design. You should have the struct separated in its own file. In this case you could even hand the complete data object to the next view controller.

Using NSView in NSTableView?

I have searched a lot and but I am not able to find solution for my problem. Seems it is very easy for everyone.
I am trying to create a NSTableView which have NSView cells. But those NSViews will be complicated so I decided to use separate NSViewController for these NSViews so that I can handle actions separately.
Here is what I have done-
This is My StoryBoard-
I am trying to use ViewController for each of cells in NSTableView.
This View is very simple currently(only two labels) but there will be few buttons and image views in future.
the view controller have identifier "rowCell".
I have did this-
extension CMCenterTableViewController:NSTableViewDataSource{
func numberOfRowsInTableView(tableView: NSTableView) -> Int {
return self.conversationData.count
}
func tableView(tableView: NSTableView, viewForTableColumn tableColumn: NSTableColumn?, row: Int) -> NSView?
{
var centralStoryBoard = NSStoryboard(name: "Main", bundle: nil)
var rowCellID: AnyObject? = centralStoryBoard?.instantiateControllerWithIdentifier("rowCell")
var castedView = rowCellID as! CMRowCellView
castedView.view.frame = CGRectMake(self.view.frame.minX, self.view.frame.minY, self.view.frame.width, 75)
(castedView as CMRowCellView).SubjectLable.stringValue = (conversationData[row].valueForKey("subject") as? String)!
(castedView as CMRowCellView).FromLable.stringValue = (conversationData[row].valueForKey("fromAddress") as? String)!
return castedView . view
}
}
This is viewController -
import Cocoa
class CMRowCellView: NSViewController {
#IBOutlet weak var FromLable: NSTextField!
#IBOutlet weak var SubjectLable: NSTextField!
var from:String?
var subject:String?
override func viewDidLoad() {
super.viewDidLoad()
// Do view setup here.
}
}
This works Ok but there is slowness in scroll because views are loaded each time and they are not being reused.
My problem is I want to reuse these view with makeViewWithIdentifier, But I can't find a way to do so.
And also Is it correct way to use view controllers in NSTableView?
Thanks for your help.

Resources