action buttons on tweet cell swift - ios

I am using twitter fabric and have a table view being populated with a 'tweetsWithJSONArray'.
I am trying to add the showAction boolean to my tweet cells in my tableview func cellForRowAtIndexPath method like so:
let tweet = tweets[indexPath.row]
let cell = feedTableView.dequeueReusableCellWithIdentifier(tweetTableReuseIdentifier, forIndexPath: indexPath) as! TWTRTweetTableViewCell
cell.configureWithTweet(tweet)
self.feedTableView.allowsSelection = true
cell.tweetView.delegate = self
cell.tweetView.showActionButtons = true
But I'm getting the error that TWTRTweetView dos not have a member named showActionButtons. I am a bit confused by this as the example on the fabric docs looks as follows:
let tweetView = TWTRTweetView(tweet: newlyLoadedTweet)
tweetView.showActionButtons = true
self.addSubview(tweetView)
link:
https://docs.fabric.io/ios/twitter/show-tweets.html
I realise I have it done a bit differently but I'm still unsure how to apply the showActionBoolean in the right way in my case. My tableview has an attached segment control and only when the final segment is selected do I populate my table with a tweetsWithJsonArray, that is why I couldn't take the example from the docs as is.

I had the same problem and after inspecting the SDK documentation I simply found out that setting "showTweetActions" to true works instead of
using the Fabric sample to do it (it gave me an error on "newlyLoadedTweet")
//swift
showTweetActions = true
Hope this can help ;)

Related

Stop Diffable Data Source scrolling to top after refresh

How can I stop a diffable data source scrolling the view to the top after applying the snapshot. I currently have this...
fileprivate func configureDataSource() {
self.datasource = UICollectionViewDiffableDataSource<Section, PostDetail>(collectionView: self.collectionView) {
(collectionView: UICollectionView, indexPath: IndexPath, userComment: PostDetail) -> UICollectionViewCell? in
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: PostDetailCell.reuseIdentifier, for: indexPath) as? PostDetailCell else { fatalError("Cannot create cell")}
cell.user = self.user
cell.postDetail = userComment
cell.likeCommentDelegate = self
return cell
}
var snapshot = NSDiffableDataSourceSnapshot<Section, PostDetail>()
snapshot.appendSections([.main])
snapshot.appendItems(self.userComments)
self.datasource.apply(snapshot, animatingDifferences: true)
}
fileprivate func applySnapshot() {
//let contentOffset = self.collectionView.contentOffset
var snapshot = NSDiffableDataSourceSnapshot<Section, PostDetail>()
snapshot.appendSections([.main])
snapshot.appendItems(self.userComments)
self.datasource.apply(snapshot, animatingDifferences: false)
//self.collectionView.contentOffset = contentOffset
}
store the offset, then reapply it. Sometimes it works perfectly and sometimes the view jumps. Is there a better way of doing this?
The source of this problem is probably your Item identifier type - the UserComment.
Diffable data source uses the hash of your item identifier type to detect if it is a new instance or an old one which is represented currently.
If you implement Hashable protocol manually, and you use a UUID which is generated whenever a new instance of the type is initialized, this misguides the Diffable data source and tells it this is a new instance of item identifier. So the previous ones must be deleted and the new ones should be represented. This causes the table or collection view to scroll after applying snapshot.
To solve that replace the uuid with one of the properties of the type that you know is unique or more generally use a technique to generate the same hash value for identical instances.
So to summarize, the general idea is to pass instances of the item identifiers with the same hash values to the snapshot to tell the Diffable data source that these items are not new and there is no need to delete previous ones and insert these ones. In this case you will not encounter unnecessary scrolls.
Starting from iOS 15
dataSource.applySnapshotUsingReloadData(snapshot, completion: nil)
Resets the UI to reflect the state of the data in the snapshot without computing a diff or animating the changes
First up: in most cases #Amirrezas answer will be the correct reason for the problem. In my case it was not the item, but the section identifier that caused the problem. That was Hashable and Identifiable with correct values, but it was a class, and therefore the hash functions were never called. Took me a while to spot that problem. Changing to a struct (and therefore adopting some things ;) ) helped in my case.
For reference here's a link to the topic on the Apple-Dev forums: https://developer.apple.com/forums/thread/657499
Hope my answer helps somebody :)
You'd think that any of these methods would work:
https://developer.apple.com/documentation/uikit/uicollectionviewdelegate/1618007-collectionview
https://developer.apple.com/documentation/uikit/uicollectionviewlayout/1617724-targetcontentoffset
But (in my case) they did not. You might get more mileage out of them, I am doing some crazy stuff with a custom UICollectionViewCompositionalLayout
What I did get to work is manually setting the offset in my custom layout class:
override func finalizeCollectionViewUpdates() {
if let offset = collectionView?.contentOffset {
collectionView?.contentOffset = targetContentOffset(forProposedContentOffset: offset)
}
super.finalizeCollectionViewUpdates()
}
where I have targetContentOffset also overridden and defined (I tried that first, didn't work, figured it was cleanest to just use that here. I suspect if you define targetContentOffset on the delegate without overriding it in the layout the above will also work, but you already need a custom layout to get this far so it's all the same.)

Q: UITests - How to get collectionCell element inside collectionView nested with TableView cell?

I'm the beginner of UITests. Currently, I have an issue that I can not access element inside collectionViewCell.
My UI elements structure:
UIViewController
UITableView
-- UITableViewCell
---> UICollectionView
----> UICollectionViewCell
-----> The element that I would like to get.
I've tried with the code below:
let tableCellContainer = app.tables["HomeRVMPTableView"].cells.element(boundBy: 0) // Get the first Cell of TableView
let collectionContainer = tableCellContainer.collectionViews["ContainerItemCollectionView"].cells.element(boundBy: 1) // Get the second Cell inside collectionView
let collectionElement = collectionContainer.staticTexts["BuyCashCard"]
XCTAssertFalse(!collectionElement.exists) // FAILED
Is there any way to access collectionViewCell/tableViewCell easier? I'm so tired when start working UITests with that.
Thank you guys for helping me, I just found another way to access the collection view inside the tableview.
Here is my code:
let tableCellContainer = app.tables["MainTableView"].cells.element(boundBy: 1)
let cell = tableCellContainer.staticTexts["Brazil"]
cell.tap()
XCTAssert(cell.exists)
Hope this will help another guy who has the same issue like me.
For that line to fail, the collectionElement must actually exist. Replace your failing line with XCTAssert(collectionElement.exists)
XCTAssertFalse fails when the condition is true. XCTAssert (equivalent to XCTAssertTrue) succeeds when the condition is true.

Find table cell in Xcode ui testing Swift

I am new on Xcode + ios testing. I am going to automate ui of an existing ios project in swift. The problem is that I am unable to find table view of a view. Here is my code which i used to finding a cell from table view but this is not working in this case:
XCUIApplication().tables.cells.allElementsBoundByIndex[1].tap()
I am attaching screenshot of the view flow. The ios code of view is not written by me.
So you want to find a tableView's cell and then tap on it.
This solution is posted after testing in Xcode 9.0 beta 6, using Swift 4
As mentioned by Oletha in a comment, it's a good idea to understand the hierarchy of your view by printing the debugDescription:
let app = XCUIApplication()
override func setUp() {
super.setUp()
continueAfterFailure = false
app.launch()
print(app.debugDescription)
}
The print statement will give you a detailed list of views and their hierarchy.
Next, you should add an accessibilityIdentifier to your tableview and cell as follows:
a) Inside your viewDidLoad() or any other relevant function of the controller-
myTableView.accessibilityIdentifier = “myUniqueTableViewIdentifier”
b) Inside your tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) function-
cell.accessibilityIdentifier = "myCell_\(indexPath.row)"
Once done, you can write the following code in your test case to get the desired results:
let myTable = app.tables.matching(identifier: "myUniqueTableViewIdentifier")
let cell = myTable.cells.element(matching: .cell, identifier: "myCell_0")
cell.tap()
Note that this will simply help you find and tap the required cell, you can add some XCTAssert checks inside your test case to make it more useful.
P.S.: There are many guides online which can help you learn the UI testing with Xcode. e.g.: https://blog.metova.com/guide-xcode-ui-test/
Objective-C version of Kushal's answer. Last step is more simplified, though.
A- Where you define your table (usually in the viewDidLoad of its viewController), define its accessibilityIdentifier:
_myTable.accessibilityIdentifier = #"MyOptionsTable";
B- In cellForRowAtIndexPath, give each cell an accessibilityIdentifier:
cell.accessibilityIdentifier = #"MySpecialCell";
C- In your test case, get the table, then tap on the cell:
XCUIApplication *app = [[XCUIApplication alloc] init];
XCUIElement *table = app.tables[#"MyOptionsTable"];
XCUIElement *cell = table.cells[#"MySpecialCell"];
[cell tap];
First set cell accessibilityIdentifier:
cell.accessibilityIdentifier = "Cell_\(indexPath.row)"
Get cell by identifier, then tap cell:
let cell = app.cells.element(matching: .cell, identifier: "Cell_0")
cell.tap()
If you have the cell's accessibilityIdentifier in place, the following straight-forward solution works well for me:
app.cells["your_accessibility_identifer"].tap()
The most voted answer doesn't work for me, with the table view access identifier and the table view cell identifier. It finds the table view at first, then when it comes to finding the cell it simply fails.
Source: 1.

Custom swipeable Table View Cell, Close other once new one open

I'm following tutorial from raywenderlich (How To Make A Swipeable Table View Cell With Actions) site, that shows you how to create custom cell with layers and delegate.
Now I got everything working correctly, buy I would like one of my cells to close if other cell open, how can I achieve this? or Like Messenger app, don't allow users to open another cell option unless they close the current one.
I can't wrap my head around this, I see few other people also ask the same question in comments, but no one reply.
Anyone with Objective-C knowledge, it's okay, I can translate it to swift myself.
The reason I'm using this tutorial, is because the Apple API doesn't allow custom button (using PaintCode) to be used as Action button.
I find a very simple solution for anyone else who trying to achieve the same method.
Create a Method - closeOtherCells:
Since we store all cells in NSMutableSet we can see which ones are available for closing.
func closeOtherCells(close close: Bool){
if close{
//Check For Available Cell
for cells in cellsCurrentEditing {
//Get Table Cells at indexPath
var cellToClose: CustomTableViewCell = self.tableView.cellForRowAtIndexPath(cells as! NSIndexPath) as! CustomTableViewCell
//Call Reset Method in our Custom Cell.
cellToClose.resetConstraintContstantsToZero(true, notifyDelegateDidClose: true)
}
}
}
Now Simply in your cellDidOpen: delegate method call closeOtherCells: with true parameter.
func cellDidOpen(cell: UITableViewCell) {
//Close Other Cells
closeOtherCells(close: true)
//Store Open Cell in NSMutableSet
let indexPath: NSIndexPath = self.tableView.indexPathForCell(cell)!
self.cellsCurrentEditing.addObject(indexPath)
}
I hope this help others. :)

Changing an Image within a Cell with UIGestureRecognizer attached to UIImageView - Swift

I've been wrestling for hours with the following problem: I have an image in each of my cells of a UITableView which I'd like to toggle when tapped. Currently, in the function where I establish the cells,
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath)
I have the following code which attaches the UIGestureRecognizer to the image in each cell:
cell.imageView!.userInteractionEnabled = true
cell.imageView!.tag = indexPath.row
var tapped:UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "TappedImage:")
tapped.numberOfTapsRequired = 1
cell.imageView!.addGestureRecognizer(tapped)
Currently, I am trying to figure out how to change that cell's image in:
func TappedImage(sender:UITapGestureRecognizer)
It seems that I am able to change the background for the image, or set it to hidden, for example, but not actually change it. Maybe this is a question of accessing the cell? I've been trying to figure out how I would define it in this function from the imageView tag, but I also have sections, which I think may make the tag less relevant (as I would need to reference both section and row). I have the toggle function written which passes in a cell which I could easily call from this function if I can access the exact cell. Any advice or sample code is much appreciated. Thank you for reading.
Thank you

Resources