Duplicate Button actions on different View Controllers? - ios

I have a button on one of my view controllers which controls a score action (counter).
Can someone help me duplicating the button and the action it takes and place the duplicate on a separate ViewController?
I need this for a workout Application i'm making and I want to get the action Proof of concept complete before I implement it into my App.
I have attached my Xcode Project with the stage I am now on.
Ive tried passing the name of the action button from the main VC to the newest but I've had no luck.
https://github.com/Mulreany93/NewVCActionButton

I saw in your GitHub that you have an empty class called ViewControllerNewButton, which inherits from UIViewController. I suggest making your scorebutton into a new class called something like e.g. ScoreButton, which should inherit directly from UIButton - class ScoreButton: UIButton {...} Then in each View Controller you can create your scorebutton: let scoreButtonTest = ScoreButton() and then you can use e.g. conversion functions like scoreButtonTest.someConversion() from your ScoreButton class.
If I am on the wrong track, feel free to comment but as far as I can tell you are just trying to use your button in multiple VCs and that's a good place to try inheritance.
Edit for clarification:
class ScoreButton: UIButton {
func someConversion() {
...
}
}

Related

Add analytics event to log each ViewController's name in the project

I have a project in which I need to log an analytics event whenever any View Controller (log the name of the View Controller) comes on screen.
I was trying to avoid littering all of my existing View Controller classes with call to the analytics SDK.
I tried making an AnalyticsViewController and all my View Controllers would subclass this View Controller, and then I add analytics event in AnalyticsViewController class's viewDidLoad method. But the problem with this approach is that AnalyticsViewController does not which child View Controller is the call coming from.
I am using Swift 3.0. I believe that Swift with its powerful language features should be able provide me with an abstraction of some sorts.
Is there any way through this problem without littering all the View Controllers?
You were on the right track. Making a UIViewController parent class is a good idea.
In viewDidLoad method you can just add this:
let className = NSStringFromClass(self.classForCoder)
It will give you the name of current loaded view controller and then you can use that name in your event to specify which view controller was actually loaded.
Edit: added example.
So your parent's viewDidLoad would look something like this:
override func viewDidLoad() {
super.viewDidLoad()
let className = NSStringFromClass(self.classForCoder)
sendEvent(withViewControllerName: className)
}
The answer given by #JPetric is an amazing starting point. I just had to do a little modification to get it to work.
I've put this in my AnalyticsViewController to retrieve the name of the current subclass.
private func currentClassName() -> String? {
return NSStringFromClass(self.classForCoder).components(separatedBy: ".").last
}

Connecting event handler to custom UIView component

I have a custom UIView component called ControlsDockView and I have a couple of buttons in the view. I know that you can add the click event for the buttons directly to the UIViewController and proceed further. But would it be possible for me to add the event handler to the ControlsDockView? If so, how?
For android, I know we can directly have the event handler written in the view but is it different with swift?
Do I have to go through the view controller for it? Maybe it is a newbie question but I need to know how I can proceed with this.
Thanks in advance for your help
Yes. You can create an action for a button in your custom view. Easiest way is probably to ctrl-drag from interface builder to your view code.
you will then get an IBAction func actionHandler(sender: UIButton) {} in your view code.
Another way to set this up is by adding the action to the buttons in your loadFromNib method or constructor in the custom view.
However, be careful about adding any kind of logic that isn't directly related to the view in those actions as it's considered an extremely bad coding practise to add business logic to you views in such a manner.

Check which UIViewController my custom button class is on w/o Storyboard

I have created a custom class for my UIBarButtonItem (refreshIndicator.m). This button will be on many different view controllers, all push-segued from my MainViewController/NavigationController.
Instead of dragging an outlet onto every single ViewController.m file for iPhone storyboard THEN iPad storyboard (ugh, still targeting iOS7), I want to know if there is a way to complete my task simply within my UIBarButtonItem custom class. I've looked around everywhere but I haven't quite found an answer to this,
All I need to do is check which UIViewController is present, check the last time the page was refreshed, and then based on that time, set an image for the UIBarButtonItem. (I've got this part figured out though, unless someone has a better suggestion). How can I check for the current UIViewController within a custom button class? Is this possible?
Does it need to know which view controller its on so it can tell that vc it was pressed? If that's the case, then use your button's inherited target and action properties. On every vc that contains an instance of the button, in view did load:
self.myRefreshIndicator.target = self;
self.myRefreshIndicator.action = #selector(myRefreshIndicatorTapped:);
- (void)myRefreshIndicatorTapped:(id)sender {
// do whatever
}
More generally, its better to have knowledge about the model flow to the views from the vc, and knowledge of user actions flow from the views. Under that principal, your custom button could have a method like:
- (void)timeIntervalSinceLastRefresh:(NSTimeInterval)seconds {
// change how I look based on how many seconds are passed
}
And your vcs:
NSTimeInterval interval = [[NSDate date] timeIntervalSinceDate:self.lastRefreshDate];
[self.myRefreshIndicator timeIntervalSinceLastRefresh:interval];
If you really must go from a subview to a view controller, you could follow the responder chain as suggested in a few of the answers here (but I would go to great lengths to avoid this sort of thing).
It is possible to achieve this, but the solution is everything but elegant. It is one way of getting around the basic principles of iOS and is strongly discouraged.
One of the ways is to walk through the responder chain, posted by Phil M.
Another way is to look through all subviews of view controllers until you find the button.
Both ways are considered a bad practice and should be avoided.
For your particular case, I would rethink the structure of having a separate instance of the bar button. For example, you could rework it into a single UIButton instance that gets displayed over every view controller and it can also act as a singleton.

Best design/pattern to use for first-use tutorial in app?

The background:
I have an app with 5 tabs. The first time a user navigates to each tab, I would like to show a one-time "tutorial". I intend to do this by creating a "TutorialViewController" that will handle displaying these "tutorial" views and will have buttons for next/back etc...
The problem:
I'm not sure the best pattern to use for implementing the logic for whether or not to show these screens and instantiating the "TutorialViewController" to display them. The goal is to have a single line of code (a single method call) that would show the tutorial if necessary. I'm trying to avoid duplication of code across the 5 view controllers. The problem is where/how to implement this single method. As a class method on TutorialViewController? As a global C function?
Things I've considered:
1) Implementing a class method on TutorialViewController called "displayTutorialIfNecessary". In this case, each view controller that has a tutorial would call this class method from their "viewDidAppear" methods. This class method would check to see if the tutorial has already been shown, and if not, it would instantiate a TutorialViewController object to handle to display it. In this option, I guess I would have to pass in "self" from each calling view controller and the class method would use that to display the TutorialViewController.
2) Implementing a class method on TutorialViewController called "tutorialShouldBeDisplayedForScreen: ". In this option, each calling view controller would call this method, and if it returns true, each vc would instantiate and present the "TutorialViewController" which would handle displaying the tutorial.
I'm sure there is a "best practice" or a pattern that fits this scenario, but I'm not sure what the best implementation is. Thanks in advance for your recommendations.
To summarize: Instead of having something like this in each view controller:
if ([TutorialViewController shouldDisplayTutorialForScreen:<someEnum>])
{
TutorialViewController *myTutorialVC = [[TutorialViewController alloc] init];
[self displayModalViewController: myTutorialVC];
}
I'd like something more like this:
[FirstUseViewController displayTutorialIfNecessaryForScreen: <someEnum> forParentViewController: self];
store the tutorial has shown state into NSUserDefaults and use factory method design pattern to let each UIViewController you'll need create and return tutorial UIViewController like:
- (UIViewController *)tutorialVC {
return [[MYHomeScreenTutorialVC alloc] init];
}

How to create new objects consisting of multiple cocoa touch objects?

I want to make a group of cocoa touch objects behave like one object, Is this possible?
For instance, say we had a SuperButton that consisted of two UIButtons, spaced by 10.
Let's just say their frame is set.
Is it possible to make a wrapper class ?
that I can init and call -
[_view addSubview:SuperButton] on and have it create both buttons?
I'm not entirely sure on the terminology for what I'm trying to do so it's hard to find any help on google.
Okay, Let me ask you this question first. So you want to create a SuperButton, when ever you call it it should layout the two buttons for you, is this right ?. YES you can do this. Create a new XIB, which is having just a view. configure your buttons in it. Create your super button class and assign it to this xib. You should be able to call this class and it will return view which can be added to your main view controller.

Resources