problem solved thank You. That had to do with the mistake above that is not displayed here
Post
Replies
Boosts
Views
Activity
I fixed the issue by creating custom UIView that holds a UITableView inside.
However if anyone can explain why it did't work by simply laying out some constraints in a VC, I will be more than grateful
EDIT: It seems like I did not fix the issue with that at all. Table view does not populate and syntax error is the same
Hey guys. A little bit of clarification. The problem with the table View had a different nature which I solved. However, the error stayed, I have realised that its connected to these constraints:
addNoteTextField.topAnchor.constraint(equalTo: view.topAnchor, constant: padding),
addNoteTextField.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: padding),
addNoteTextField.widthAnchor.constraint(equalToConstant: 270),
addNoteTextField.heightAnchor.constraint(equalToConstant: 50),
addNoteButton.topAnchor.constraint(equalTo: view.topAnchor, constant: padding),
addNoteButton.leadingAnchor.constraint(equalTo: addNoteTextField.trailingAnchor, constant: padding),
addNoteButton.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -padding),
addNoteButton.heightAnchor.constraint(equalToConstant: 50),
])
What could be possibly wrong with them?
Hey, thanks for getting back to me.
Here is my code for the DataSource
Swift
private func configureDataSource() {
let cellRegistration = UICollectionView.CellRegistrationSearchTweetsCell, Tweet{ (cell, indexPath, tweet) in
cell.set(with: tweet, user: self.user)
cell.delegateSafari = self
}
dataSource = UICollectionViewDiffableDataSourceSection, Tweet(collectionView: collectionView, cellProvider: { (collectionView, indexPath, tweet) - UICollectionViewCell? in
return collectionView.dequeueConfiguredReusableCell(using: cellRegistration, for: indexPath, item: tweet)
})
dataSource.supplementaryViewProvider = { (collectionView, kind, indexPath) in
let header = collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: SearchTweetsVCCollectionHeader.reuseId, for: indexPath) as! SearchTweetsVCCollectionHeader
header.set(with: self.user)
return header
}
}
Not sure what do you mean by the "definition of the cell class"? Thanks!
Animation happens in @objc private func addToFavoritesTapped (Line 44), function animateButtonView(sender) (Line 64) is called (on line 45) that takes alpha to 0, then changes an image, and takes alpha back to 1.
import UIKit
// MARK: - Protocols and Delegates
protocol SearchTweetsCellDelegates: class {
func didRequestSafari(with urlString: String?)
}
final class SearchTweetsCell: UICollectionViewCell {
// MARK: - Declarations
static let reuseId = "cell"
let addToFavoritesButton = UIButton()
var timeDateLabel = UILabel()
let tweetBodyLabel = UserSearchVCTextView()
var mediaStackView = UIStackView()
let seeOnlineButton = UIButton()
var sharesView = CellMediaInfoView()
var likesView = CellMediaInfoView()
var goSafariButton = GoSafariButton()
weak var delegateSafari: SearchTweetsCellDelegates!
var tweet: Tweet!
var user: User!
var urlString: String?
// MARK: - Initialise & Override
override init(frame: CGRect) {
super.init(frame: frame)
configureCell()
configureUIElements()
layoutUI()
configureMediaStackView()
configureGoSafariButton()
}
override func prepareForReuse() { self.goSafariButton.isHidden = false }
required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
// MARK: - @Objectives
@objc private func addToFavoritesTapped(sender: UIView) {
animateButtonView(sender)
let favorite = fromTweetToFavoriteTweet(user: user, tweet: tweet)
PersistenceManager.updateWithTweets(favoriteTweet: favorite, persistenceAction: .add) { [weak self] (error) in
guard self != nil else { return }
guard let error = error else {
print("sucess")
return
}
print(error.rawValue)
}
self.addToFavoritesButton.isEnabled = false
}
@objc private func didTapGoSafariButton(_ sender: UIView) {
delegateSafari.didRequestSafari(with: urlString)
}
// MARK: - Animations
private func animateButtonView(_ viewToAnimate: UIView) {
UIView.animate(withDuration: 0.2, animations: {viewToAnimate.alpha = 0}) { [weak self] (true) in
guard let self = self else { return }
switch true {
case true:
DispatchQueue.main.async { self.addToFavoritesButton.setImage(SFSymbolsAsImg.checkmark, for: .normal) }
UIView.animate(withDuration: 0.2, animations: {viewToAnimate.alpha = 1} )
case false:
return
}
}
}
// MARK: - Called outside
func set(with usersTweet: Tweet, user: User) {
self.user = user
tweet = usersTweet
urlString = usersTweet.urlToExpandWithSafari
tweetBodyLabel.text = usersTweet.tweetText
timeDateLabel.text = usersTweet.createdAt.formatToTwitterPostDate()
sharesView.set(itemInfoType: .shares, with: usersTweet.retweetCounter.convertToKMFormatStr())
likesView.set(itemInfoType: .likes, with: usersTweet.likesCounter.convertToKMFormatStr())
if tweet.urlToExpandWithSafari == nil { goSafariButton.isEnabled = true }
self.goSafariButton.setTitle(TweetStrings.seeFull, for: .normal)
}
// MARK: - Cell Configuration
private func fromTweetToFavoriteTweet(user: User ,tweet: Tweet) - FavoriteTweet {
let favoriteTweet = FavoriteTweet(twitsId: tweet.twitsId,
name: user.name,
tweetText: tweet.tweetText,
profileImageUrl: user.profileImageUrl,
urlToExpandWithSafari: tweet.urlToExpandWithSafari,
likesCounter: tweet.likesCounter,
retweetCounter: tweet.retweetCounter,
createdAt: tweet.createdAt)
return favoriteTweet
}
private func configureCell() {
backgroundColor = .secondarySystemBackground
layer.cornerRadius = 15
}
private func configureGoSafariButton() {
goSafariButton.addTarget(self, action: #selector(didTapGoSafariButton), for: .touchUpInside)
}
private func configureMediaStackView() {
mediaStackView.axis = .horizontal
mediaStackView.distribution = .equalSpacing
mediaStackView.alignment = .center
mediaStackView.addArrangedSubview(sharesView)
mediaStackView.addArrangedSubview(likesView)
}
private func configureUIElements() {
timeDateLabel.textColor = .systemGray
timeDateLabel.textAlignment = .center
addToFavoritesButton.setImage(SFSymbolsAsImg.plus, for: .normal)
addToFavoritesButton.tintColor = ColorsTwitter.twitterBlue
addToFavoritesButton.addTarget(self, action: #selector(addToFavoritesTapped), for: .touchUpInside)
}
// MARK: - Layout Configuration
private func layoutUI() {
addSubviews(addToFavoritesButton, timeDateLabel, tweetBodyLabel, mediaStackView, goSafariButton)
tamicToFalse(addToFavoritesButton, mediaStackView, timeDateLabel)
let mediaLeadingPadding: CGFloat = DeviceTypes.isiPhoneSE || DeviceTypes.isiPhone8Zoomed ? 10 : 30
let mediaWidthMltp: CGFloat = DeviceTypes.isiPhoneSE || DeviceTypes.isiPhone8Zoomed ? 0.55 : 0.5
NSLayoutConstraint.activate([ ... ]) // Removed from the post for less text
}
}
Hi. I am happy to send you the whole project and any additional info that you may find valuable if you could just find me on LinkedIn (Jakub Gawecki, curly hair on a profile image) or Facebok (Kuba Gawecki, profile image with the dog). Should be easy, not too many people with my name.
So what you suggesting is to, for example:
Add var favorite: Bool parameter to my struct.
When the data of a tweet is fetched from JSON, set favorite's default value to false.
When the button addToFavorite is pushed, toggle favorites value to true and save that object with some persistence manager,
Then, every time data is fetched again for the same user to get his/her tweets, do a check if the tweet exists in persistence manager with the favorite parameter set to true, and if it does, set its UI accordingly?
I hope it makes sense what I just wrote.
Fantastic. Thank You.
Would you mind telling me why is not a good idea to use id with Swift?
Sorry I forgot to paste the solution I came up with. It should all work now.
enum Section { case main }
var dataSource: UICollectionViewDiffableDataSource<Section, Follower.ID>!
// MARK: - Collection View configurations
fileprivate lazy var collectionView: UICollectionView = {
let collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: UIHelper.createCompositionalLayout())
collectionView.delegate = self
collectionView.backgroundColor = .systemBackground
collectionView.register(FollowersCollectionHeaderView.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: FollowersCollectionHeaderView.reuseId)
view.addSubview(collectionView)
return collectionView
}()
fileprivate lazy var snapshot: NSDiffableDataSourceSnapshot<Section, Follower.ID> = {
var snapshot = NSDiffableDataSourceSnapshot<Section, Follower.ID>()
snapshot.appendSections([.main])
let itemIdentifiers = followers.map { $0.id }
snapshot.appendItems(itemIdentifiers, toSection: .main)
dataSource.apply(snapshot, animatingDifferences: true)
return snapshot
}()
fileprivate func updateData(with followers: [Follower]) {
snapshot = NSDiffableDataSourceSnapshot<Section, Follower.ID>()
snapshot.appendSections([.main])
let itemIdentifiers = followers.map { $0.id }
snapshot.appendItems(itemIdentifiers, toSection: .main)
dataSource.apply(snapshot, animatingDifferences: true)
}
fileprivate func configureDataSource() {
let cellRegistration = UICollectionView.CellRegistration<FollowerCell, Follower.ID> { [weak self]
cell, indexPath, followerID in
guard let self = self else { return }
let followerArray = self.followers.filter { $0.id == followerID }
if let follower = followerArray.first {
cell.set(on: follower)
}
}
dataSource = UICollectionViewDiffableDataSource<Section, Follower.ID>(collectionView: collectionView) {
collectionView, indexPath, itemIdentifier in
return collectionView.dequeueConfiguredReusableCell(using: cellRegistration,
for: indexPath,
item: itemIdentifier)
}
let headerRegistration = createSectionHeaderRegistration()
dataSource.supplementaryViewProvider = { collectionView, elementKind, indexPath in
return collectionView.dequeueConfiguredReusableSupplementary(using: headerRegistration, for: indexPath)
}
}
fileprivate func createSectionHeaderRegistration() -> UICollectionView.SupplementaryRegistration<FollowersCollectionHeaderView> {
return UICollectionView.SupplementaryRegistration<FollowersCollectionHeaderView>(
elementKind: FollowersCollectionHeaderView.reuseId) { [weak self] supplementaryView, elementKind, indexPath in
guard let self = self else { return }
supplementaryView.set(with: self.user)
}
}
It worked for me, thanks!
Hi mate. Have you been able to resolve that issue? If so, could you please share some more code? Thanks.
Hey Barrylium. Why don't you try it with the SceneKit? Using SceneKit for that purpose is easier.
Hey Sparta. Has the memory leak subject been resolved? Thanks for letting me know
Extra note:
It's worth adding that this behaviour is the opposite from SwiftUI implementation.
From Apple's TipKitExamples app:
Image(systemName: "wand.and.stars")
.imageScale(.large)
// Add the popover to the feature you want to highlight.
.popoverTip(tip)
.onTapGesture {
// Invalidate the tip when someone uses the feature.
tip.invalidate(reason: .actionPerformed)
}
This piece of code does not disable the touch for underlaying views
Problem solved itself after multiple cache cleaning