i'm so beginner developer in ios world, and it's the first time i try to make a little application.
my app used UItableview to show the content i've get it from server, i use this tutorial: https://www.youtube.com/watch?v=JG_AMY_gSDQ
in this tutorial: they used the main view controller and add table view to it, so when i try to add pull to refresh to my view, i can't because i didn't use UITableViewController.
so is there any way to refresh my content without using UITableViewController ?
and thank you so mush for answering.
Yes this is possible. You will need to initialize UIRefreshControl manually then addsubview to your tableView
var refreshControl:UIRefreshControl!
override func viewDidLoad() {
super.viewDidLoad()
refreshControl = UIRefreshControl()
refreshControl.tintColor = UIColor.redColor()
refreshControl.addTarget(self, action: "refresh:", forControlEvents: UIControlEvents.ValueChanged)
myTableView.addSubview(refreshControl)
}
func refresh(sender: AnyObject){
// this function will be called whenever you pull your list for refresh
}
Related
My senior was reviewing my code and he found that I have used UIButton addTarget method like this
override func viewDidLoad() {
super.viewDidLoad()
self.btnAccount.addTarget(self, action: #selector(Accounts(_:)), for: .touchUpInside)
}
Now he is saying that you should not use addTarget in viewDidLoad it will take time(kind of memory management thing I didn't get it) to load view controller but I didn't find it relevant
that's why I am asking this question did I made some mistake by doing this should I always make actions
I didn't hear of that and even if it is true, you should never try to do premature optimization on your app. UIButton is a UIControl object, which follows an event-listener pattern, which is often implemented with a hashmap (NSDictionary in Objective-C) of targets ('aka' Listeners or Observers) and it is not very time-consuming operation.
I personally prefer to setup all UI component right at the beginning:
lazy var btnAccount: UIButton = {
let btn = UIButton
// setup button's appearance
btn.addTarget(self, action: #selector(Accounts(_:)), for: .touchUpInside)
return btn
}()
P.S. Please ask him about the source of the fact and let me know.
I have a viewController EditMessage which has two UITextFields (UITextView) which use the keyboard and they work great. This part is basic standard stuff. When the keyboard is displayed, I register a tag gesture for the entire view, so that if the user clicks anywhere else, I dismiss the keyboard:
self.view.addGestureRecognizer(UITapGestureRecognizer(target: self,
action: #selector(dismissKeyboard)))
In dismissKeyboard, this all works fine:
#objc func dismissKeyboard(sender: Any) {
self.view.endEditing(true)
}
However, I have a menu button(thumbnail image) implemented as a child view controller (UIViewController) on the same EditMessage view, which hijacks the screen via UIApplication.shared.keyWindow() to display an overlay and menu on the bottom of the screen. Built using the model/code from Brian Voong's YouTube channel to replicate a YouTube style slide in menu from the bottom. However, the keyboard is in the way. Since the child is a different view controller "endEditing" doesn't work (or maybe I am referencing the wrong view?).
class ButtonPickerController : UIViewController,
UIGestureRecognizerDelegate, UINavigationControllerDelegate {
var maxSize = CGFloat(60)
let thumbnail: UIImageView = {
let thumbnail = UIImageView()
thumbnail.backgroundColor = UIColor.lightGray
return thumbnail
}()
override func viewDidLoad() {
super.viewDidLoad()
let tap = UITapGestureRecognizer(target: self, action: #selector(self.buttonTapped(sender:)))
tap.delegate = self
view.addGestureRecognizer(tap)
//view.backgroundColor = .yellow
view.contentMode = .scaleAspectFit
thumbnail.frame = CGRect(x: 0, y: 0, width: self.maxSize, height: self.maxSize)
setupSubviews()
}
Can someone point me in a good direction? This is my first question so hopefully I am asking properly.
I figured it out in the end. Thank you for the help. In my child view controller I did used the following statement when the button was tapped:
#objc func buttonTapped(sender: UITapGestureRecognizer? = nil) {
self.parent!.view.endEditing(true)
}
First, its not a good way to present overlays as UIViewController.
But a solution good be, to give the second viewcontroller a reference to the first one before viewDidLoad is called. Do you use Segues ? So in prepare would be the right place. In the second viewcontroller you create a property for the first one and then use this property as target when you create the UITapGestureRecognizer.
Another way is using a protocol and delegation.
I need help fixing this issue! I am adding pull to refresh to my table view. When I pull to refresh I want the articles to refresh. If someone who knows this would help me would be great, and if there is anything else wrong too.
Argument of '#selector' does not refer to an '#objc' method, property, or initializer
The error is here:
refreshControl.addTarget(self, action: #selector(fetchArticles(fromSource: source)), for: .valueChanged)
return refreshControl
}()
Here is the function fetchArticles:
#objc func fetchArticles(fromSource provider: String){
...
}
You have to add another function to refresh articles, because you are passing a parameter:
#objc func refreshArticles() {
self.fetchArticles(fromSource: self.source))
}
And addTarget like this:
refreshControl.addTarget(self, action: #selector(refreshArticles), for: .valueChanged)
Also, Do not miss to add refreshControl to tableView, as such:
tableView.addSubview(refreshControl)
Update Add following line once fetchArticles completes, as such:
refreshControl.endRefreshing()
You are using session.dataTask so this must go inside:
DispatchQueue.main.async {
refreshControl.endRefreshing()
}
I use a UIRefreshControl in my tableview for pull new data. But when I define the control, below error shows. I've googled for a while, but find nothing useful.
I use Xcode Version 9.2 (9C40b), swift4, IOS11.2
Cannot override mutable property 'refreshControl' of type
'UIRefreshControl?' with covariant type 'UIRefreshControl'
var refreshControl = UIRefreshControl()
If you want to define another control, then change the name... refreshControl is a UIScrollView/UITableViewController ivar since iOS10/iOS6 [respectively]. You're trying to redefine it and that is what causing the error. Or you can use the supplied one of course.
You probably meant something like self.refreshControl = UIRefreshControl()
Swift 4/5
override func viewDidLoad() {
super.viewDidLoad()
self.refreshControl = UIRefreshControl()
self.refreshControl!.attributedTitle = NSAttributedString(string: "Pull to refresh")
self.refreshControl!.addTarget(self, action: #selector(refresh(sender:)), for: UIControl.Event.valueChanged)
}
#objc func refresh(sender:AnyObject) {
// Code to refresh table view
self.refreshControl!.endRefreshing()
}
The compiler is preventing you from specifying a more stringent requirement in your subclass than the one set by your superclass.
Suppose the compiler allowed you to override an Optional property with a non-Optional type. What happens if someone does this:
let tableView: UITableView = CoolTableViewSubclass()
tableView.refreshControl = nil // but my overridden property can't be nil!
As a subclass, you need to work ok when someone treats you as if you were your superclass. So the compiler stops you in this case because it can already tell that you're breaking this rule.
Mike Ash wrote this up in an unsurprisingly good post if you're curious.
So I have enabled refreshing for the table view in Storyboard and put this code into the viewDidLoad() :
refreshControl?.addTarget(self, action: #selector(ViewController.refresh(sender:)), for: .valueChanged)
and this is the refresh function:
func refresh(sender: AnyObject) {
print("a")
self.tableView.reloadData()
refreshControl?.endRefreshing()
}
The problem is that when I pull to refresh, it does not print "a"(put this for testing) and it does not end refreshing. Why?
Since you're already using Storyboards, try connecting your refresh control through IBActions (valueChanged) and see if it works. Follow this link for a guide