Creating a class that builds modal views to display announcements or issues

Multi tool use
Multi tool use

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
0
down vote

favorite












I'm looking to create a class that will display a template pop-up to the user to alert them to new features/updates and when their calendar isn't synchronised correctly.



I'd like to do this in a manner that makes this reusable for other projects, and fully testable. This is the code so far:



AnnouncementManager



 /// Builds all announcements with the right content: any kind of alerts, advices, tutorials or news
class AnnouncementsManager

/**
Contains Calendar help Announcement action
Whenever we detect the user corporate Cloud Calendar is not synced, we show an alert
The call to action will open the Help@IBM website with instructions to solve the issue
- returns: Calendar Help View as an Announcment View Controller
*/
static func getCalendarHelp() -> AnnouncementViewController
let calendar = AnnouncementItem(title: "CalendarHelp.Title".localized, subtitle: "CalendarHelp.Subtitle".localized, image: #imageLiteral(resourceName: "calendar-alert"))
let cloud = AnnouncementItem(title: "CalendarHelp.CloudTitle".localized, subtitle: "CalendarHelp.CloudSubtitle".localized, image: #imageLiteral(resourceName: "cloud-mail"))
let noCloud = AnnouncementItem(title: "CalendarHelp.NoCloudTitle".localized, subtitle: "CalendarHelp.NoCloudSubtitle".localized, image: #imageLiteral(resourceName: "non-cloud-mail"))

return AnnouncementViewController(newsTitle: calendar, newsItems: [cloud, noCloud], action: AnnouncementAction(actionName: "CalendarHelp.Action".localized, action:
guard let url = URL(string: "https://w3.ibm.com/help/#/article/ios_setup_device/setup_apple_mail") else
return

UIApplication.shared.open(url, options: [:], completionHandler: nil)
))




AnnouncementViewController



/**
This template will be used for any kind of announcements, alerts, advices, tutorials or news
- Contains main title, maximum 3 other subitems and a button (as call to action)
- Each title and item is made itself of a title, subtitle and image
- To customize the action, an AnnouncmentAction should be paased in the intializer.
*/
class AnnouncementViewController: UIViewController

let newsTitle : AnnouncementItem
let newsItems : [AnnouncementItem]
let action : AnnouncementAction?

@IBOutlet weak var itemsStack: UIStackView!
@IBOutlet weak var titleView: UIView!
@IBOutlet weak var actionButton: UIButton!
/**
If action is nil, default action will take place (dismiss view)
*/
init(newsTitle: AnnouncementItem, newsItems: [AnnouncementItem], action: AnnouncementAction? = nil)
self.newsTitle = newsTitle
self.newsItems = newsItems
self.action = action
super.init(nibName: "Announcement", bundle: nil)


required init?(coder aDecoder: NSCoder)
fatalError("init(coder:) has not been implemented")


override func viewDidLoad()
super.viewDidLoad()
// set title values
setItem(item: newsTitle, view: titleView)
// set items
for (item, view) in zip(newsItems, itemsStack.subviews)
setItem(item: item, view: view)

// set button
setButton(with: action?.actionName ?? "Onboarding.Common.IUnderstand".localized)


// MARK: Setters
// Apply content customization to the views

private func setItem(item: AnnouncementItem, view: UIView)
for subview in view.subviews
if let imageView = subview as? UIImageView
imageView.image = item.image
else if let label = subview as? UILabel
if label.tag == 0
label.text = item.title
else if label.tag == 1
label.text = item.subtitle





private func setButton(with text: String)
actionButton.layer.cornerRadius = 6
actionButton.setTitle(text, for: .normal)
actionButton.addTarget(self, action: #selector(self.actionButtonWasClicked), for: .touchUpInside)



// MARK: Actions

/// call action function if action has been set
@objc func actionButtonWasClicked()
if let actionNeeded = action
actionNeeded.action()
else
dismissAnnouncement()



/// dismiss view
func dismissAnnouncement()
if let navigationController = navigationController
navigationController.popViewController(animated: true)
else
dismiss(animated: true, completion: nil)






AnnoncementActionsAndItems



/// Contains the action name and the action function for the actions in announcements
class AnnouncementAction
let actionName: String
let action: (() -> Void)

init(actionName: String, action: @escaping (() -> Void))
self.actionName = actionName
self.action = action



/// Each item in an announcement template
struct AnnouncementItem
let title : String
let subtitle: String
let image : UIImage

init (title: String, subtitle: String, image: UIImage)
self.title = title
self.subtitle = subtitle
self.image = image




Example Announcement:



enter image description here







share|improve this question





















  • Does the code work? codereview.stackexchange.com/help/on-topic
    – pacmaninbw
    May 14 at 13:41










  • @pacmaninbw Yes I'm looking to see how I can improve it.
    – Deco
    May 14 at 19:12











  • @pacmaninbw The part of the code to show updates to the user hasn't been implemented yet I included that just to elaborate on how the class would eventually grow. The plan so far is to just create another static function for each announcement type but I feel this break the O/C principle.
    – Deco
    May 14 at 19:20










  • It would be helpful if you make the code self-contained (such as adding the definitions of AnnouncementItem and AnnouncementAction).
    – Martin R
    May 15 at 11:36











  • @MartinR oops I missed that. Updated.
    – Deco
    May 15 at 13:07
















up vote
0
down vote

favorite












I'm looking to create a class that will display a template pop-up to the user to alert them to new features/updates and when their calendar isn't synchronised correctly.



I'd like to do this in a manner that makes this reusable for other projects, and fully testable. This is the code so far:



AnnouncementManager



 /// Builds all announcements with the right content: any kind of alerts, advices, tutorials or news
class AnnouncementsManager

/**
Contains Calendar help Announcement action
Whenever we detect the user corporate Cloud Calendar is not synced, we show an alert
The call to action will open the Help@IBM website with instructions to solve the issue
- returns: Calendar Help View as an Announcment View Controller
*/
static func getCalendarHelp() -> AnnouncementViewController
let calendar = AnnouncementItem(title: "CalendarHelp.Title".localized, subtitle: "CalendarHelp.Subtitle".localized, image: #imageLiteral(resourceName: "calendar-alert"))
let cloud = AnnouncementItem(title: "CalendarHelp.CloudTitle".localized, subtitle: "CalendarHelp.CloudSubtitle".localized, image: #imageLiteral(resourceName: "cloud-mail"))
let noCloud = AnnouncementItem(title: "CalendarHelp.NoCloudTitle".localized, subtitle: "CalendarHelp.NoCloudSubtitle".localized, image: #imageLiteral(resourceName: "non-cloud-mail"))

return AnnouncementViewController(newsTitle: calendar, newsItems: [cloud, noCloud], action: AnnouncementAction(actionName: "CalendarHelp.Action".localized, action:
guard let url = URL(string: "https://w3.ibm.com/help/#/article/ios_setup_device/setup_apple_mail") else
return

UIApplication.shared.open(url, options: [:], completionHandler: nil)
))




AnnouncementViewController



/**
This template will be used for any kind of announcements, alerts, advices, tutorials or news
- Contains main title, maximum 3 other subitems and a button (as call to action)
- Each title and item is made itself of a title, subtitle and image
- To customize the action, an AnnouncmentAction should be paased in the intializer.
*/
class AnnouncementViewController: UIViewController

let newsTitle : AnnouncementItem
let newsItems : [AnnouncementItem]
let action : AnnouncementAction?

@IBOutlet weak var itemsStack: UIStackView!
@IBOutlet weak var titleView: UIView!
@IBOutlet weak var actionButton: UIButton!
/**
If action is nil, default action will take place (dismiss view)
*/
init(newsTitle: AnnouncementItem, newsItems: [AnnouncementItem], action: AnnouncementAction? = nil)
self.newsTitle = newsTitle
self.newsItems = newsItems
self.action = action
super.init(nibName: "Announcement", bundle: nil)


required init?(coder aDecoder: NSCoder)
fatalError("init(coder:) has not been implemented")


override func viewDidLoad()
super.viewDidLoad()
// set title values
setItem(item: newsTitle, view: titleView)
// set items
for (item, view) in zip(newsItems, itemsStack.subviews)
setItem(item: item, view: view)

// set button
setButton(with: action?.actionName ?? "Onboarding.Common.IUnderstand".localized)


// MARK: Setters
// Apply content customization to the views

private func setItem(item: AnnouncementItem, view: UIView)
for subview in view.subviews
if let imageView = subview as? UIImageView
imageView.image = item.image
else if let label = subview as? UILabel
if label.tag == 0
label.text = item.title
else if label.tag == 1
label.text = item.subtitle





private func setButton(with text: String)
actionButton.layer.cornerRadius = 6
actionButton.setTitle(text, for: .normal)
actionButton.addTarget(self, action: #selector(self.actionButtonWasClicked), for: .touchUpInside)



// MARK: Actions

/// call action function if action has been set
@objc func actionButtonWasClicked()
if let actionNeeded = action
actionNeeded.action()
else
dismissAnnouncement()



/// dismiss view
func dismissAnnouncement()
if let navigationController = navigationController
navigationController.popViewController(animated: true)
else
dismiss(animated: true, completion: nil)






AnnoncementActionsAndItems



/// Contains the action name and the action function for the actions in announcements
class AnnouncementAction
let actionName: String
let action: (() -> Void)

init(actionName: String, action: @escaping (() -> Void))
self.actionName = actionName
self.action = action



/// Each item in an announcement template
struct AnnouncementItem
let title : String
let subtitle: String
let image : UIImage

init (title: String, subtitle: String, image: UIImage)
self.title = title
self.subtitle = subtitle
self.image = image




Example Announcement:



enter image description here







share|improve this question





















  • Does the code work? codereview.stackexchange.com/help/on-topic
    – pacmaninbw
    May 14 at 13:41










  • @pacmaninbw Yes I'm looking to see how I can improve it.
    – Deco
    May 14 at 19:12











  • @pacmaninbw The part of the code to show updates to the user hasn't been implemented yet I included that just to elaborate on how the class would eventually grow. The plan so far is to just create another static function for each announcement type but I feel this break the O/C principle.
    – Deco
    May 14 at 19:20










  • It would be helpful if you make the code self-contained (such as adding the definitions of AnnouncementItem and AnnouncementAction).
    – Martin R
    May 15 at 11:36











  • @MartinR oops I missed that. Updated.
    – Deco
    May 15 at 13:07












up vote
0
down vote

favorite









up vote
0
down vote

favorite











I'm looking to create a class that will display a template pop-up to the user to alert them to new features/updates and when their calendar isn't synchronised correctly.



I'd like to do this in a manner that makes this reusable for other projects, and fully testable. This is the code so far:



AnnouncementManager



 /// Builds all announcements with the right content: any kind of alerts, advices, tutorials or news
class AnnouncementsManager

/**
Contains Calendar help Announcement action
Whenever we detect the user corporate Cloud Calendar is not synced, we show an alert
The call to action will open the Help@IBM website with instructions to solve the issue
- returns: Calendar Help View as an Announcment View Controller
*/
static func getCalendarHelp() -> AnnouncementViewController
let calendar = AnnouncementItem(title: "CalendarHelp.Title".localized, subtitle: "CalendarHelp.Subtitle".localized, image: #imageLiteral(resourceName: "calendar-alert"))
let cloud = AnnouncementItem(title: "CalendarHelp.CloudTitle".localized, subtitle: "CalendarHelp.CloudSubtitle".localized, image: #imageLiteral(resourceName: "cloud-mail"))
let noCloud = AnnouncementItem(title: "CalendarHelp.NoCloudTitle".localized, subtitle: "CalendarHelp.NoCloudSubtitle".localized, image: #imageLiteral(resourceName: "non-cloud-mail"))

return AnnouncementViewController(newsTitle: calendar, newsItems: [cloud, noCloud], action: AnnouncementAction(actionName: "CalendarHelp.Action".localized, action:
guard let url = URL(string: "https://w3.ibm.com/help/#/article/ios_setup_device/setup_apple_mail") else
return

UIApplication.shared.open(url, options: [:], completionHandler: nil)
))




AnnouncementViewController



/**
This template will be used for any kind of announcements, alerts, advices, tutorials or news
- Contains main title, maximum 3 other subitems and a button (as call to action)
- Each title and item is made itself of a title, subtitle and image
- To customize the action, an AnnouncmentAction should be paased in the intializer.
*/
class AnnouncementViewController: UIViewController

let newsTitle : AnnouncementItem
let newsItems : [AnnouncementItem]
let action : AnnouncementAction?

@IBOutlet weak var itemsStack: UIStackView!
@IBOutlet weak var titleView: UIView!
@IBOutlet weak var actionButton: UIButton!
/**
If action is nil, default action will take place (dismiss view)
*/
init(newsTitle: AnnouncementItem, newsItems: [AnnouncementItem], action: AnnouncementAction? = nil)
self.newsTitle = newsTitle
self.newsItems = newsItems
self.action = action
super.init(nibName: "Announcement", bundle: nil)


required init?(coder aDecoder: NSCoder)
fatalError("init(coder:) has not been implemented")


override func viewDidLoad()
super.viewDidLoad()
// set title values
setItem(item: newsTitle, view: titleView)
// set items
for (item, view) in zip(newsItems, itemsStack.subviews)
setItem(item: item, view: view)

// set button
setButton(with: action?.actionName ?? "Onboarding.Common.IUnderstand".localized)


// MARK: Setters
// Apply content customization to the views

private func setItem(item: AnnouncementItem, view: UIView)
for subview in view.subviews
if let imageView = subview as? UIImageView
imageView.image = item.image
else if let label = subview as? UILabel
if label.tag == 0
label.text = item.title
else if label.tag == 1
label.text = item.subtitle





private func setButton(with text: String)
actionButton.layer.cornerRadius = 6
actionButton.setTitle(text, for: .normal)
actionButton.addTarget(self, action: #selector(self.actionButtonWasClicked), for: .touchUpInside)



// MARK: Actions

/// call action function if action has been set
@objc func actionButtonWasClicked()
if let actionNeeded = action
actionNeeded.action()
else
dismissAnnouncement()



/// dismiss view
func dismissAnnouncement()
if let navigationController = navigationController
navigationController.popViewController(animated: true)
else
dismiss(animated: true, completion: nil)






AnnoncementActionsAndItems



/// Contains the action name and the action function for the actions in announcements
class AnnouncementAction
let actionName: String
let action: (() -> Void)

init(actionName: String, action: @escaping (() -> Void))
self.actionName = actionName
self.action = action



/// Each item in an announcement template
struct AnnouncementItem
let title : String
let subtitle: String
let image : UIImage

init (title: String, subtitle: String, image: UIImage)
self.title = title
self.subtitle = subtitle
self.image = image




Example Announcement:



enter image description here







share|improve this question













I'm looking to create a class that will display a template pop-up to the user to alert them to new features/updates and when their calendar isn't synchronised correctly.



I'd like to do this in a manner that makes this reusable for other projects, and fully testable. This is the code so far:



AnnouncementManager



 /// Builds all announcements with the right content: any kind of alerts, advices, tutorials or news
class AnnouncementsManager

/**
Contains Calendar help Announcement action
Whenever we detect the user corporate Cloud Calendar is not synced, we show an alert
The call to action will open the Help@IBM website with instructions to solve the issue
- returns: Calendar Help View as an Announcment View Controller
*/
static func getCalendarHelp() -> AnnouncementViewController
let calendar = AnnouncementItem(title: "CalendarHelp.Title".localized, subtitle: "CalendarHelp.Subtitle".localized, image: #imageLiteral(resourceName: "calendar-alert"))
let cloud = AnnouncementItem(title: "CalendarHelp.CloudTitle".localized, subtitle: "CalendarHelp.CloudSubtitle".localized, image: #imageLiteral(resourceName: "cloud-mail"))
let noCloud = AnnouncementItem(title: "CalendarHelp.NoCloudTitle".localized, subtitle: "CalendarHelp.NoCloudSubtitle".localized, image: #imageLiteral(resourceName: "non-cloud-mail"))

return AnnouncementViewController(newsTitle: calendar, newsItems: [cloud, noCloud], action: AnnouncementAction(actionName: "CalendarHelp.Action".localized, action:
guard let url = URL(string: "https://w3.ibm.com/help/#/article/ios_setup_device/setup_apple_mail") else
return

UIApplication.shared.open(url, options: [:], completionHandler: nil)
))




AnnouncementViewController



/**
This template will be used for any kind of announcements, alerts, advices, tutorials or news
- Contains main title, maximum 3 other subitems and a button (as call to action)
- Each title and item is made itself of a title, subtitle and image
- To customize the action, an AnnouncmentAction should be paased in the intializer.
*/
class AnnouncementViewController: UIViewController

let newsTitle : AnnouncementItem
let newsItems : [AnnouncementItem]
let action : AnnouncementAction?

@IBOutlet weak var itemsStack: UIStackView!
@IBOutlet weak var titleView: UIView!
@IBOutlet weak var actionButton: UIButton!
/**
If action is nil, default action will take place (dismiss view)
*/
init(newsTitle: AnnouncementItem, newsItems: [AnnouncementItem], action: AnnouncementAction? = nil)
self.newsTitle = newsTitle
self.newsItems = newsItems
self.action = action
super.init(nibName: "Announcement", bundle: nil)


required init?(coder aDecoder: NSCoder)
fatalError("init(coder:) has not been implemented")


override func viewDidLoad()
super.viewDidLoad()
// set title values
setItem(item: newsTitle, view: titleView)
// set items
for (item, view) in zip(newsItems, itemsStack.subviews)
setItem(item: item, view: view)

// set button
setButton(with: action?.actionName ?? "Onboarding.Common.IUnderstand".localized)


// MARK: Setters
// Apply content customization to the views

private func setItem(item: AnnouncementItem, view: UIView)
for subview in view.subviews
if let imageView = subview as? UIImageView
imageView.image = item.image
else if let label = subview as? UILabel
if label.tag == 0
label.text = item.title
else if label.tag == 1
label.text = item.subtitle





private func setButton(with text: String)
actionButton.layer.cornerRadius = 6
actionButton.setTitle(text, for: .normal)
actionButton.addTarget(self, action: #selector(self.actionButtonWasClicked), for: .touchUpInside)



// MARK: Actions

/// call action function if action has been set
@objc func actionButtonWasClicked()
if let actionNeeded = action
actionNeeded.action()
else
dismissAnnouncement()



/// dismiss view
func dismissAnnouncement()
if let navigationController = navigationController
navigationController.popViewController(animated: true)
else
dismiss(animated: true, completion: nil)






AnnoncementActionsAndItems



/// Contains the action name and the action function for the actions in announcements
class AnnouncementAction
let actionName: String
let action: (() -> Void)

init(actionName: String, action: @escaping (() -> Void))
self.actionName = actionName
self.action = action



/// Each item in an announcement template
struct AnnouncementItem
let title : String
let subtitle: String
let image : UIImage

init (title: String, subtitle: String, image: UIImage)
self.title = title
self.subtitle = subtitle
self.image = image




Example Announcement:



enter image description here









share|improve this question












share|improve this question




share|improve this question








edited May 15 at 13:05
























asked May 14 at 10:05









Deco

11310




11310











  • Does the code work? codereview.stackexchange.com/help/on-topic
    – pacmaninbw
    May 14 at 13:41










  • @pacmaninbw Yes I'm looking to see how I can improve it.
    – Deco
    May 14 at 19:12











  • @pacmaninbw The part of the code to show updates to the user hasn't been implemented yet I included that just to elaborate on how the class would eventually grow. The plan so far is to just create another static function for each announcement type but I feel this break the O/C principle.
    – Deco
    May 14 at 19:20










  • It would be helpful if you make the code self-contained (such as adding the definitions of AnnouncementItem and AnnouncementAction).
    – Martin R
    May 15 at 11:36











  • @MartinR oops I missed that. Updated.
    – Deco
    May 15 at 13:07
















  • Does the code work? codereview.stackexchange.com/help/on-topic
    – pacmaninbw
    May 14 at 13:41










  • @pacmaninbw Yes I'm looking to see how I can improve it.
    – Deco
    May 14 at 19:12











  • @pacmaninbw The part of the code to show updates to the user hasn't been implemented yet I included that just to elaborate on how the class would eventually grow. The plan so far is to just create another static function for each announcement type but I feel this break the O/C principle.
    – Deco
    May 14 at 19:20










  • It would be helpful if you make the code self-contained (such as adding the definitions of AnnouncementItem and AnnouncementAction).
    – Martin R
    May 15 at 11:36











  • @MartinR oops I missed that. Updated.
    – Deco
    May 15 at 13:07















Does the code work? codereview.stackexchange.com/help/on-topic
– pacmaninbw
May 14 at 13:41




Does the code work? codereview.stackexchange.com/help/on-topic
– pacmaninbw
May 14 at 13:41












@pacmaninbw Yes I'm looking to see how I can improve it.
– Deco
May 14 at 19:12





@pacmaninbw Yes I'm looking to see how I can improve it.
– Deco
May 14 at 19:12













@pacmaninbw The part of the code to show updates to the user hasn't been implemented yet I included that just to elaborate on how the class would eventually grow. The plan so far is to just create another static function for each announcement type but I feel this break the O/C principle.
– Deco
May 14 at 19:20




@pacmaninbw The part of the code to show updates to the user hasn't been implemented yet I included that just to elaborate on how the class would eventually grow. The plan so far is to just create another static function for each announcement type but I feel this break the O/C principle.
– Deco
May 14 at 19:20












It would be helpful if you make the code self-contained (such as adding the definitions of AnnouncementItem and AnnouncementAction).
– Martin R
May 15 at 11:36





It would be helpful if you make the code self-contained (such as adding the definitions of AnnouncementItem and AnnouncementAction).
– Martin R
May 15 at 11:36













@MartinR oops I missed that. Updated.
– Deco
May 15 at 13:07




@MartinR oops I missed that. Updated.
– Deco
May 15 at 13:07















active

oldest

votes











Your Answer




StackExchange.ifUsing("editor", function ()
return StackExchange.using("mathjaxEditing", function ()
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
);
);
, "mathjax-editing");

StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "196"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
convertImagesToLinks: false,
noModals: false,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);








 

draft saved


draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f194355%2fcreating-a-class-that-builds-modal-views-to-display-announcements-or-issues%23new-answer', 'question_page');

);

Post as a guest



































active

oldest

votes













active

oldest

votes









active

oldest

votes






active

oldest

votes










 

draft saved


draft discarded


























 


draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f194355%2fcreating-a-class-that-builds-modal-views-to-display-announcements-or-issues%23new-answer', 'question_page');

);

Post as a guest













































































qA0Y0KwaLAgui KRGnqYk
DW88,EdJ,j5K10rPr9kl4UtSm,LzenR

Popular posts from this blog

Chat program with C++ and SFML

Function to Return a JSON Like Objects Using VBA Collections and Arrays

Python - Quiz Game with Tkinter