Swift 4 - UIRefreshControl on vertical UICollectionView lags - swift

For some reason, my pull to refresh is really hard to complete. What I mean by that, is that in order to pull-to-refresh I have to begin from the very top of my collection view and scroll down to the very bottom... sometimes I even have to use a second finger in order to scroll more to make it work!
Here's how I initialise the refresher:
private var refresher: UIRefreshControl!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
refresher = UIRefreshControl()
refresher.addTarget(self, action: #selector(self.requestRefreshContent), for: .valueChanged)
if #available(iOS 10.0, *) {
schoolPostsCollectionView.refreshControl = refresher
}
else {
schoolPostsCollectionView.addSubview(refresher)
}
refresher.beginRefreshing()
}
Here's how I call beginRefreshing():
private func getContentOfSchool() {
someBackgroundServerCall() {
// some code
...
DispatchQueue.main.async {
self.refresher.endRefreshing()
self.schoolPostsCollectionView.reloadData()
}
}
}
Any idea why is this happening?

try this one....
refresher = UIRefreshControl()
refresher.attributedTitle = NSAttributedString(string: "Refreshing...", attributes: nil)
refresher.tintColor = UIColor.black
refresher.addTarget(self, action: #selector(self.requestRefreshContent), for: .valueChanged)
if #available(iOS 10.0, *) {
schoolPostsCollectionView.refreshControl = refresher
} else {
schoolPostsCollectionView.backgroundView = refresher
}

Related

UINavigationBar LargeTitle , searchbar didn't work

enter image description here
enter image description here
I want to make it like the picture below, but it comes out like the picture above.
Here is My Code.
lazy var button = UIDropDownButton().then {
$0.setAction().subscribe(onNext: {
switch $0 {
case .popularity: break
// 인기순 정렬 코드
case .suggestion: break
// 추천순 정렬 코드
case .lowestPrice: break
// 최저가순 정렬 코드
}
})
.disposed(by: disposeBag)
}
lazy var barButtonItem = UIBarButtonItem(customView: button)
override func viewDidLoad() {
super.viewDidLoad()
setNavigationBar()
}
override func viewWillAppear(_ animated: Bool) {
setNavigationBar()
}
private func setNavigationBar() {
setLargeTitleNavigationBar(title: "제품")
self.navigationItem.rightBarButtonItem = barButtonItem
let searchController = UISearchController(searchResultsController: nil)
self.navigationItem.searchController = searchController
}
setLargeTitleNavigationBar Method is here.
extension UIViewController {
func setLargeTitleNavigationBar(title: String) {
self.navigationController?.navigationBar.prefersLargeTitles = true
self.navigationController?.setBackButon()
self.navigationController?.navigationBar.backgroundColor = nil
self.navigationController?.navigationBar.shadowImage = nil
self.navigationController?.navigationBar.setBackgroundImage(nil, for: UIBarMetrics.default)
self.navigationItem.title = title
}
I don't know how to solve this problem.
I like Snapkit, but I can read storyboard.
use this
navigationController?.navigationBar.prefersLargeTitles = true
navigationItem.largeTitleDisplayMode = .always

Gesture recognizer is not working on UIView

I'm trying to get a few gesture recognisers to work on a UIView. The UIview is in this case a retrieved SVG image, the library that I use is SwiftSVG.
But the actual added image is a UIView, so I think that is not the problem?
override func viewDidLoad() {
super.viewDidLoad()
let svgURL = URL(string: "https://openclipart.org/download/181651/manhammock.svg")!
let hammock = UIView(SVGURL: svgURL) { (svgLayer) in
svgLayer.fillColor = UIColor(red:0.8, green:0.16, blue:0.32, alpha:1.00).cgColor
svgLayer.resizeToFit(self.v2imageview.bounds)
}
hammock.isUserInteractionEnabled = true
let tap = UITapGestureRecognizer(target: self, action: #selector(self.handleTap(_:)))
hammock.isUserInteractionEnabled = true;
hammock.addGestureRecognizer(tap)
self.view.addSubview(hammock)
}
// function which is triggered when handleTap is called
#objc func handleTap(_ sender: UITapGestureRecognizer) {
print("Hello World")
}
How can I make the recognizer work?
Thanks
You need to set a frame
hammock.frame = ///
or constraints

How to fix UIButton not responding to touch?

I am working an app with quizzes, have 4 UIButtons (custom type) on subview which is custom view and none of the buttons is recognising the action even though I set the target. I have to do it programatically.
I have tried setting isUserInteractionEnabled but it is not working. Buttons are on the view, respecting the bounds.
Here, viewDidLoad from InitialViewController:
override func viewDidLoad()
{
super.viewDidLoad()
self.questionView?.firstanswer!.isEnabled = true
self.questionView?.firstanswer!.addTarget(self, action: #selector(self.answerTheQuestion), for: UIControl.Event.touchUpInside)
self.questionView?.secondanswer!.addTarget(self, action: #selector(self.answerTheQuestion), for: UIControl.Event.touchUpInside)
self.questionView?.thirdanswer!.addTarget(self, action: #selector(self.answerTheQuestion), for: UIControl.Event.touchUpInside)
self.questionView?.fourthanswer!.addTarget(self, action: #selector(self.answerTheQuestion), for: UIControl.Event.touchUpInside)
}
Here is the action function:
#objc func answerTheQuestion(_sender:UIButton) {
print("aa")
if let questionsAnswers = self.quizzes?.quizzes[self.randomNumber!]["questions"] as? [[String:Any]] {
if (questionsAnswers[self.randomQuestion!]["question"] as? String) != nil {
if let correctAnswer = questionsAnswers[self.randomQuestion!]["correct_answer"] as? String {
if _sender.titleLabel?.text == correctAnswer {
_sender.backgroundColor = UIColor.green
} else {
_sender.backgroundColor = UIColor.red
}
}
}
}
}
View and buttons are added normally, only tap is not working.
It should go red when the answer is wrong, and green when it is right. Questions and everything else is added normally, but it even won't print "aaa" in the beginning of the target function. Pls help, thanks!!

Hello, I am getting two errors for textFieldDidChange ( Swift)

Can someone please help me out? I am getting these two errors
use of unresolved identifier
and
use of local variable textFieldDidChange before its declaration
Here is my code
override func viewDidLoad() {
super.viewDidLoad()
// Setting text field delegates
emailTextField.delegate = self
passwordTextField.delegate = self
// Disable login button until both textFields are not nil
textField.addTarget(self, action: #selector(textFieldDidChange), for: UIControlEvents.editingChanged)
}
func textFieldDidChange() {
if (emailTextField.text?.isEmpty)! || (passwordTextField.text?.isEmpty)! {
print("text is empty")
loginButton.isEnabled = false
loginButton.alpha = 0.33
} else {
loginButton.isEnabled = true
loginButton.alpha = 0.55
}
}
Edit
Question has been answered however I noticed the button would enable after I typed into the first textField. So I changed the && to || because I wanted the button to be disabled until both textFields weren't empty. Just for anyone who has this issue as well.
Your textFieldDidChange method should be outside the viewDidLoad and should be prefix-ed with #objc since it is a selector.
class YourClass: UIViewController {
// Your code
override func viewDidLoad() {
super.viewDidLoad()
// Setting text field delegates
emailTextField.delegate = self
passwordTextField.delegate = self
// Disable login button until both textFields are not nil
emailTextField.addTarget(self, action: #selector(textFieldDidChange), for: UIControlEvents.editingChanged)
passwordTextField.addTarget(self, action: #selector(textFieldDidChange), for: UIControlEvents.editingChanged)
}
#objc func textFieldDidChange() {
if (emailTextField.text?.isEmpty)! && (passwordTextField.text?.isEmpty)! {
print("text is empty")
loginButton.isEnabled = false
loginButton.alpha = 0.33
} else {
loginButton.isEnabled = true
loginButton.alpha = 0.55
}
}
}
And the target should be added to the respective text fields - emailTextField and passwordTextField.
You have missed to place "}" for viewDidLoad method
override func viewDidLoad() {
super.viewDidLoad()
// Setting text field delegates
emailTextField.delegate = self
passwordTextField.delegate = self
// Disable login button until both textFields are not nil
textField.addTarget(self, action: #selector(textFieldDidChange), for: UIControlEvents.editingChanged)
}
#objc func textFieldDidChange() {
if (emailTextField.text?.isEmpty)! && (passwordTextField.text?.isEmpty)! {
print("text is empty")
loginButton.isEnabled = false
loginButton.alpha = 0.33
} else {
loginButton.isEnabled = true
loginButton.alpha = 0.55
}
}

AVPlayercontroller - Adding Overlay Subviews

Depends upon the PlaybackControl Visibity How to show and hide the Custom Subview added in contentOverlayView?
I want to do like Youtube TVOS app did.
I tried with UIPressesEvent but it is not giving me the exact touch events. It is giving me these:
override func pressesBegan(presses: Set<UIPress>, withEvent event: UIPressesEvent?) {
for item in presses {
switch item.type {
case .Menu:
self.customViews.alpha = 0
case .PlayPause:
self.player?.pause()
self.customViews.alpha = 0
default:
self.setVisibilityToPreviewView()
}
}
}
func setVisibilityToPreviewView () { //This wont work in all cases.
if self.previewView.alpha == 1 {
self.previewView.alpha = 0
} else {
self.previewView.alpha = 1
}
}
But with this Touch events i can only show and hide the subviews.
It should be hidden when the playbackcontrol is Hidden.
If I get the PlayBackControl Visibility values I don't need to worry about hiding these subviews.
Apple is Using AVNowPlayingPlaybackControlsViewController. It is not open for developers.
So I need to find some other better way to do this.
Please guide me how to do it.
You can register a tapGesture recognizer and then set its allowPressTypes property to UIPressType.Select, something like this
let tapRecognizer = UITapGestureRecognizer(target: self, action: "onSelect:")
tapRecognizer.allowedPressTypes = [NSNumber(integer: UIPressType.Select.rawValue)];
self.view.addGestureRecognizer(tapRecognizer)
And inside your action button show or hide custom overlays.
Example: Add this code inside a view controller and on tap (selecting at empty area on front of remote, touch area) you will see a message on console.
override func viewDidLoad() {
super.viewDidLoad()
let tapGesture = UITapGestureRecognizer(target: self, action: "onSelect")
tapGesture.allowedPressTypes = [NSNumber(integer: UIPressType.Select.rawValue)]
self.view.addGestureRecognizer(tapGesture);
}
func onSelect(){
print("this is select gesture handler method");
}
Update: Below is the code which will create AVPlayerController and will register tapGestureRecognizer to playervc.view.
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
playContent()
}
func playContent(){
let urlString = "<contentURL>"
guard let url = NSURL(string: urlString) else{
return
}
let avPlayer = AVPlayer(URL: url)
let playerVC = AVPlayerViewController()
playerVC.player = avPlayer
self.playerObj = playerVC
let tapGesture = UITapGestureRecognizer(target: self, action: "onSelect")
tapGesture.allowedPressTypes = [NSNumber(integer: UIPressType.Select.rawValue)]
self.view.addGestureRecognizer(tapGesture);
playerVC.view.addGestureRecognizer(tapGesture)
self.presentViewController(playerVC, animated: true, completion: nil);
}
Give a try to this, I think it should work fine.