I have this UISwitch that I connected from my storyboard to my controller.
#property (weak, nonatomic) IBOutlet UISwitch *wantHelp;
What I am trying to do is to configure it so that the app can know when the state of the uiswitch has changed.
I looked at examples online and they show something similar to this:
-(IBAction)helpToggle:(id)sender
{
if (wantHelp.on)
{
NSLog(#"yes");
}
else
{
NSLog(#"No");
}
}
but they seem to refer to different ids like the wantHelp or the helpToggle and many of the examples use this kind of a heading -(IBAction)helpToggle:(id)sender but I am confused what the "sender" is configured from and what it should be in my case.
Thanks for your help in helping me understand what to do.
sender is the object that's sending the message. If you have your UISwitch hooked up to send a helpToggle: action to an object that implements it, sender will be a pointer to the switch.
If you want to check it out for yourself, add a line like this to your code:
`NSLog(#"sender is: %#", sender);`
Every time you flip the switch (wantHelp), the method helpToggle is called. When helpToggle is called, the if statements check if the conditions are true, in this case (wantHelp.on). If wantHelp is on, then the code within that if statement is called, otherwise the else statement is called.
As for the sender tag, it's what allows for communication for the method back to the switch I believe.
Usual:
Object > Method
Sender:
Object > Method > Back to Object
Related
I'm very new to Swift, and trying to create an app where Swiping between pages works normally but also involves a change in background color based on swipe distance.
Consequently, I want to "hijack" the swipe gesture, so I can add some behavior to it. The best I can find for how to do that is this question/answer.
Translating the code from the chosen answer into Swift 3, I added the following code to my RootViewController's viewDidLoad function:
for subview in (pageViewController?.view.subviews)!{
if let coercedView = subview as? UIScrollView {
coercedView.delegate = (self as! UIScrollViewDelegate)
}
}
My impression was that the above code would let me delegate functions (such as scrollViewDidScroll to the class in which I'm writing the above code, such that I can define that function, call super.scrollViewDidScroll, and then add any other functionality I want.
Unfortunately, the above code, which doesn't throw any compilation errors, does throw an error when I try to build the app:
Could not cast value of type 'My_App.RootViewController' (0x102cbf740) to 'UIScrollViewDelegate' (0x1052b2b00).
Moreover, when I try to write override func scrollViewDidScroll in my class, I get a compilation error telling me the function doesn't exist to override, which makes me think even if I got past the error, it wouldn't get called, and this isn't the right way to handle this issue.
I'm sorry this is such a noobish question, but I'm really quite confused about the basic architecture of how to solve this, and whether I understand the given answer correctly, and what's going wrong.
Am I interpreting delegate and that answer correctly?
Am I delegating to the correct object? (Is that the right terminology here?)
Is there a better way to handle this?
Am I coercing/casting improperly? Should I instead do:
view.delegate = (SomeHandMadeViewDelegateWhichDefinesScrollViewDidScroll as! UIScrollViewDelegate)
or something similar/different (another nested casting with let coercedSelf = self as? UIScrollViewDelegate or something?
Thanks!
If I understand your question correctly, you want to catch some scroll position and stuff right ? Then do
class RootViewController {
// Your stuff
for subview in pageViewController!.view.subviews {
if let coercedView = subview as? UIScrollView {
coercedView.delegate = self
}
}
extension RootViewController : UIScrollViewDelegate {
// Your scrollView stuff there
}
I have seen everywhere that delegate variable is always set to self.
thirdClass.delegate = self
So i want something like
thirdViewController.delegate = firstViewControllerToDo
In my case,
let thirdClassVar = thirdClass()
thirdClassVar.namVar = "somnam"
thirdClassVar.delegate = firstViewControllerToDo
self.performSegueWithIdentifier("gtoFirstViewcontroller", sender: self)
When i click on button in second screen, it wil return back to first screen but in background I want to do some calculation in thirdClass and after completion of that, it shud display a message in first screen.
How can i achieve this or is there any other way of getting this done.
You want doing something but you do something with wrong way. I think you can do this process with UIButton and IBAction functions, change your algorith for this process.
I have a custom UIView (called GridView) that I initialize and then add to a ViewController (DetailViewController). GridView contains several UIButtons and I would like to know in DetailViewController when those buttons are touched. I'm new to Swift and am wondering what is the best pattern to use to get those events?
If you want to do this with notifications, use 1:
func postNotificationName(_ notificationName: String,
object notificationSender: AnyObject?)
in the method that is triggered by your button. Then, in your DetailViewController, add a listener when it is initialized with 2:
func addObserver(_ notificationObserver: AnyObject,
selector notificationSelector: Selector,
name notificationName: String?,
object notificationSender: AnyObject?)
Both functions can be called from NSNotificationCenter.defaultCenter().
Another method would be to add callbacks which you connect once you initialize the GridView in your DetailViewController. A callback is essentially a closure:
var callback : (() -> Void)?
which you can instantiate when needed, e.g.
// In DetailViewController initialization
gridView = GridView()
gridView.callback = { self.doSomething() }
In GridView you can trigger the callback like this:
func onButton()
{
callback?()
}
The callback will only execute, if unwrapping succeeds. Please ensure, that you have read Automatic Reference Counting, because these constructs may lead to strong reference cycles.
What's the difference? You can connect the callback only once (at least with the method I've showed here), but when it triggers, the receiver immediately executes its code. For notifications, you can have multiple receivers but there is some delay in event delivery.
Lets assume your GridView implementation is like as follows:
class GridView : UIView {
// Initializing buttons
let button1:UIButton = UIButton(...)
let button2:UIButton = UIButton(...)
// ...
// Adding buttons to view
self.addSubview(button1)
self.addSubview(button2)
// ...
}
Now, we will add selector methods which will be called when a button is touched. Lets assume implementation of your view controller is like as follows:
class DetailViewController : UIViewController {
let myView:GridView = GridView(...)
myView.button1.addTarget(self, action: "actionForButton1:", forControlEvents: UIControlEvents.TouchUpInside)
myView.button2.addTarget(self, action: "actionForButton2:", forControlEvents: UIControlEvents.TouchUpInside)
// ...
func actionForButton1(sender: UIButton!) {
// Your actions when button 1 is pressed
}
// ... Selectors for other buttons
}
I have to say that my example approach is not a good example for encapsulation principles of Object-Oriented Programming, but I have written like this because you are new to Swift and this code is easy to understand. If you want to prevent duplicate codes such as writing different selectors for each button and if you want to set properties of your view as private to prevent access from "outside" like I just did in DetailViewController, there are much much better solutions. I hope it just helps you!
I think you better create a class called GridView that is inherited from the UIView. Then, you can connect all you UI element with you class as IBOutlet or whatever using tag something like that. Later on, you can ask the instance of GridView in DetailViewController so that you can connect as IBAction.
Encapsulation is one of the principles of OOP.
I have a simple question about event handling in iOS applications... suppose you have an app with some buttons that react to the TouchUpInside event calling the same action, what is the best way within the action method to understand what is the button that triggered the event? I know that it can be easily done using the title of the button, but I think it is not the best way if you have a localized app in which button text may change (unless it is possible to reverse the localization of the title, i.e. retrieve the original string from a localized string)... is there a good practice about this topic? Should I use some other property of buttons to distinguish among different buttons?
Thank you in advance for any help.
There is something called a "Tag" that you can set for UIButtons, or anything that can respond to an event for that matter. If you are using Interface Builder, click the attributes inspector for the item and select a value for the tag (integer). In your code do something like this...
...
- (IBAction)buttonReceived:(id)sender
{
if ([sender tag] == 1) {
//Do something
}
else if ([sender tag] == 2) {
//Do something else
}
}
In addition to the tag property, or just in case you are already using the tag for some other purpose that would mean duplicate tag values for one or more different buttons, you can always set up an IBOutlet ivar to each button you needed to check, and then in the IBAction, do something like this:
- (IBAction)buttonReceived:(UIButton *)sender
{
if (sender == myButtonA) {
// processing for button A
}
else if (sender == myButtonB) {
// processing for button B
}
}
It is a bit more work, but it can come in handy at times.
I am a new iOS developer. I am trying to figure out how to take the return value from a viewcontroller and do a string compare to identify the type of viewcontroller. My code will hopefully make this clearer:
I have an instance of a viewcontroller called "
playTimeVC". If I do this:
NSLog(#"hello %#", playTimeVC)
;
I get the following return:
2011-08-20 18:26:33.968 Arrangements[37730:207] hello "<"PlayTimeViewController: 0x58836e0">"
How can I use this return and do some string comparison. ie:
(in Perl)
if ( [playTimeVC] =~ /PlayTimeViewController/) {
// This is the one
}
Another question related to what I am trying to do:
When the user clicks on the home button and they are in a certain viewcontroller, is there any method within that controller that is called or does it go directly to applicationWillResignActive? How about when the user comes back into the app, does it call any method in the VC before resuming?
Thank you in advance.
Eric
The method isKindOfClass of NSObject should suit your needs. You can use it like that:
if ([playTimeVC isKindOfClass: [PlayTimeViewController class]]) {
// do something
}
About your second question. I'm not sure if the viewWillDisappear is called when the user presses the home button. But you can check that by putting an NSLog statement into your viewWillDisappear and check the console.