Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

passing data between vcs using delegate and protocol #13

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

jimmygtz15
Copy link

No description provided.

@jimmygtz15 jimmygtz15 requested review from paulofierro and ivancr May 30, 2019 13:46

import UIKit

protocol canRecieve {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Names of protocols, classes, structs, etc should all be capitalised. The name should also be descriptive, and spelled correctly (receive).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would add that even then I find this name wrong. The typical naming convention for something like this is {name of the VC}Delegate. In this case it would be: protocol JimmySecondViewControllerDelegate: class {

While delegates use protocols they have a specific use case and conventions. When you work in teams following platform and community conventions is super important.



@IBAction func passItBack(_ sender: Any) {
delegate?.dataRecieved(data: textField.text!)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should guard that the text field actually contains text, rather than force unwrapping.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, there's very few instances where it does make sense to force unwrap this is not one of them.


@IBAction func passItBack(_ sender: Any) {
delegate?.dataRecieved(data: textField.text!)
self.navigationController?.popViewController(animated: true)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

self isn't necessary.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. You only need to use self when dealing with a closure (for example in a closure after a WebService response comes in.


var data = ""

@IBOutlet var label: UILabel!
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IBOutlets should be declared as private (we don't want outsiders to modify them) and weak.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Private makes sense. @ivancr regarding this, should IBOutlets be weak or strong, and why?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically VC is not the owner of the label, the VC's view is and the VC already has a strong reference to its view.

If the VC also kept strong references to the view's children (e.g. this label) then those won't be deallocated if the view was to get swapped out. There may be use cases where you'd want a strong outlet, but I haven't run into one yet. YMMV 😃

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apple recommends that in the ARC age your IBOutlets should be strong:
https://stackoverflow.com/questions/7678469/should-iboutlets-be-strong-or-weak-under-arc

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ivancr i watched that session and was curious as to why they said that, as their documentation, Xcode defaults and sample code reflects the opposite.

I like this roundup: https://cocoacasts.com/should-outlets-be-weak-or-strong/

TLDR: It doesn't really matter — just be consistent.

@IBAction func passItBack(_ sender: Any) {
delegate?.dataRecieved(data: textField.text!)
self.navigationController?.popViewController(animated: true)
// dismiss(animated: true, completion: nil)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code that isn't necessary should be removed to avoid confusion.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jimmygtz15 Instead of commenting, can just delete the commented code.


if indexPath.row == 10 {
let storyboard = UIStoryboard(name: "Jimmy", bundle: nil)
let destination = storyboard.instantiateViewController(withIdentifier: "JimmyViewController") as! JimmyViewController
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💂

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of the if statement, you can attach the if statement action to the switch statement and then return, example:

`case 10:
let storyboard = UIStoryboard...

return`

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't use a storyboard. Another important lesson to learn here is that you're working on a codebase with a team and you should conform to the style and architecture of it. Nobody else is using storyboards and you shouldn't either.
Be a nice team citizen and conform to the style or convince the team that we should change the style. Don't go rogue though.

<fontDescription key="fontDescription" type="system" pointSize="25"/>
<textInputTraits key="textInputTraits"/>
</textField>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ASx-aW-Sso">
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You may want to add leading/trailing constraints to avoid the text from disappearing off screen if the label contents are very long.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Give it some constraints

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or better yet, get rid of the storyboard and do it programmatically. You can pair with @gionoa and he'll show you the ways of the force.


var delegate : canRecieve?

var data = ""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renaming to initialData may make it a little clearer what the role of this variable is.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Always important for names to make sense.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would also go further and add that using the noun data makes this too generic. This is text we're talking here, it's a very specific type of data. The name should reflect not only in its use case but also its identity.

import UIKit

protocol canRecieve {
func dataRecieved(data: String)
Copy link
Member

@paulofierro paulofierro May 30, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function signature should also include the sender, so the delegate knows who called it:

func dataRecieved(from viewController: UIViewController, data: String)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know that you (Jimmy) were trying to follow the protocol pattern of a capability but I think you should scrap this idea and think of it as a Delegate specific to JimmySecondViewController. Then the function should be a specific need of JimmySecondViewController to communicate to another object. Maybe func didEnterText(_ text: String).

}


@IBAction func passItBack(_ sender: Any) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While this pattern works, it assumes that the previous view controller is the same as its delegate. A slightly better pattern may be to send the data back to the delegate and then allow the delegate to control any navigation (in this case popping the VC).

However, a much better approach is to use unwind segues here as they handle all of this for you, without the need of a delegate protocol or handling the navigation yourself. This is a great tutorial on this type of segue: https://matteomanferdini.com/unwind-segue/

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Didn't know that! Awesome!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm sure there's somebody out there using these and they have their merits but I've never seen or work in any team that used them. I'd highly recommend you go the Delegate pattern.

Also, each part of the whole system should be named accordingly. This IBAction maybe happens when you tap a button, then make the name say that. What you do inside is another story for me.

Copy link
Contributor

@ivancr ivancr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're doing great man, please don't be discouraged by any comments. There's no progress if there's pain, embrace the growing pains.


import UIKit

protocol canRecieve {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would add that even then I find this name wrong. The typical naming convention for something like this is {name of the VC}Delegate. In this case it would be: protocol JimmySecondViewControllerDelegate: class {

While delegates use protocols they have a specific use case and conventions. When you work in teams following platform and community conventions is super important.

import UIKit

protocol canRecieve {
func dataRecieved(data: String)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know that you (Jimmy) were trying to follow the protocol pattern of a capability but I think you should scrap this idea and think of it as a Delegate specific to JimmySecondViewController. Then the function should be a specific need of JimmySecondViewController to communicate to another object. Maybe func didEnterText(_ text: String).


class JimmySecondViewController: UIViewController {

var delegate : canRecieve?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me introduce you to memory leaks. Let me know if you see why you have memory leak here and how you'd fix it.

Also the space should only go after the :. Like this:

Suggested change
var delegate : canRecieve?
var delegate: canRecieve?


var delegate : canRecieve?

var data = ""
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would also go further and add that using the noun data makes this too generic. This is text we're talking here, it's a very specific type of data. The name should reflect not only in its use case but also its identity.


var data = ""

@IBOutlet var label: UILabel!
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apple recommends that in the ARC age your IBOutlets should be strong:
https://stackoverflow.com/questions/7678469/should-iboutlets-be-strong-or-weak-under-arc


}


Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Empty spaces



@IBAction func buttonPressed(_ sender: Any) {
performSegue(withIdentifier: "sendDataForwards", sender: self)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or just don't use segues, they're gross.


let secondVC = segue.destination as! JimmySecondViewController

secondVC.data = textField.text!
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If JimmySecondViewController requires a string to be used, then it should initialized with it.

}
}

func dataRecieved(data: String) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, this is pretty much a community standard. It should go at the end of the VC something like this:

extension JimmyViewController: JimmySecondViewController {

}


if indexPath.row == 10 {
let storyboard = UIStoryboard(name: "Jimmy", bundle: nil)
let destination = storyboard.instantiateViewController(withIdentifier: "JimmyViewController") as! JimmyViewController
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't use a storyboard. Another important lesson to learn here is that you're working on a codebase with a team and you should conform to the style and architecture of it. Nobody else is using storyboards and you shouldn't either.
Be a nice team citizen and conform to the style or convince the team that we should change the style. Don't go rogue though.

@jimmygtz15
Copy link
Author

jimmygtz15 commented May 31, 2019 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants