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

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













































































Popular posts from this blog

Chat program with C++ and SFML

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

Will my employers contract hold up in court?