Building a Reusable Automated Scrolling Message Control

A Tutorial That Builds an iOS App and a Reusable Control From the Ground Up

For my 1Goal app, I wanted to have an automated scrolling message at the bottom of the main screen.  I built one for 1Goal and then turned it into a reusable control.

This article demonstrates how to build and integrate such a reusable automated scrolling message control for an iOS app. The result will look like news and sports channels where the bottom of the screen has continuously scrolling content in addition to the main broadcast.

This article will describe the steps in detail, and you can also find the completed project on GitHub.

Although the focus of this article is the reusable scrolling message control, the detailed tutorial in this article should also be an excellent resource for anyone fairly new to iOS development who wants to learn how to build an iOS app from the ground up.

The fundamentals of continuous scrolling are based on Apple’s StreetScroller, which illustrates a methodology to make manual touch scrolling appear infinite. This tutorial builds upon the same underlying technique to achieve automated scrolling, and incorporates other additional features into a reusable control.

The app that will be developed will demonstrate the following:

  • Automated scrolling that is controlled by a timer and does not involve user interaction.
  • Auto Layout to support any iOS device size and orientation without having separate xib files.
  • Custom UIView implemented in a xib file, then used within another UIView in Interface Builder.
  • Creation of an empty project and main view without a storyboard in Xcode 6, which does not have a template for a non-storyboard empty project.

We will first create the empty application in Xcode, and then we’ll build the reusable control, then add the control to our main screen that will have a continuous scrolling message at the bottom. We will also add a switch to control the message. The result of this project will look like the screenshot below, with the bottom banner containing a message that continuously scrolls across the screen.

iOS Simulator Screen Shot Mar 6, 2015, 1.03.34 PM

Note: Following the steps in the tutorial will result in all project files being in the same directory.  After building the project according to the tutorial, I moved the 3 reusable control files into their own folder with a corresponding group in Xcode.  I did this to make it easier for anyone that wants to obtain the reusable control source code only and not build the project based on the tutorial. If you go through the tutorial, just remember that if you are comparing to the GitHub version, you’ll see those 3 files in their own folder but yours will be all together for simplicity.

UIScrollView Backgrounder and Scrolling Logic

Before we begin coding, I’ll briefly explain the technique that StreetScroller used to achieve the illusion of infinite scrolling using touch gestures. The same techniques are used when the scrolling is automated to be dynamic without user interaction.

As we go through the tutorial, you can reference back to the diagram below to gain an understanding of how it works, but we’ll start with a brief overview.

The concept central to implementing AutomatedScrollView is to define a content view of the UIScrollView that is much wider than the width of the UIScrollView bounds. The diagram illustrates a content view called labelContainerView that will have UILabel subviews containing message text.

The illusion of moving text is achieved by incrementally changing the contentOffset of the UIScrollView, which defines where the beginning of the visible area is over the total area that can be scrolled across. As the contentOffset is moved, we see a different part of the message and this process is repeated at equal intervals using a timer, so it looks like the message is scrolling across the screen.

For simplicity, the height of the UIScrollView, labelContainerView UIView, and UILabel instances are all defined to be the same. The text is centered in the labels so that the presentation of the scrolling message is also centered vertically in the UIScrollView.

Create Empty Application With Single Main View

In Xcode (I’m using 6.1.1 at time of writing), select File > New > Project, and then iOS > Application > Single View Application and click Next. For the name of the project, enter AutomatedScrollingMessage or something else of your choosingI’ll refer to the project as AutomatedScrollingMessage for this tutorial. Choose Universal for Devices. Click Next. You can store the project where you like, but I do suggest you let Xcode create a Git repository in case you want to periodically commit your changes. After you click Create, you should see the project structure below.

For this project we are going to change the created project such that it does not use a storyboard, and instead we’ll transform it into an empty project like Xcode 5 and earlier were able to create.

We’ll delete the files that are no longer needed, and also create a new main UIViewController that has a xib file for building the UI with Interface Builder.

Follow the steps below to arrive at an empty project with a main UIViewController and corresponding Xib file.

Screen Shot 2015-02-26 at 4.54.54 PM
  1. Delete Main.storyboard, LaunchScreen.xib, ViewController.h, and ViewController.m. We could leave the UIViewController files and add a corresponding xib file, but I prefer to let Xcode create the two controller files and corresponding xib file at the same time. We won’t need these files, so you can select Delete and then Move To Trash.
  2. In the Supporting Files folder, click on the Info.plist file.
  3. Locate the property named Launch screen interface file base name and delete the corresponding value of LaunchScreen.  Note that we could leave in the LaunchScreen.xib and corresponding property, but it isn’t necessary for this project and it can always be made quickly at any time, so lets just remove it to have a typical empty project in this case.
  4. Locate the property named Main storyboard file base name and delete the corresponding value of Main.
  5. Select File > New > File, and then iOS > Source > Cocoa Touch Class and click Next. For the Class, enter MainViewController. Make sure Subclass of is UIViewController.  Check the Also create XIB file box so we’ll have the UIViewController and the corresponding main view XIB file for designing our main view in IB. Click Next and then Create. Specify the same folder that the AppDelegate.h and AppDelegate.m files are in by selecting the yellow folder named AutomatedScrollingMessage for the Group, and click Create.
  6. Click on the AppDelegate.m file, and add an import statement #import “MainViewController.h”, and also add a property @property (strong, nonatomic) MainViewController *viewController; between the @interface and @end declarations.
  7. Click on the AppDelegate.m file, and replace the code in the application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions method with the code below.

Save your changes and run the app. At this point, you should see it run successfully but with an empty main screen since there is only the root UIView in the MainViewController.xib file.

Configure Main View For The Reusable Scrolling View

In this section, we’ll add two UIView objects to the MainViewController.xib. One will be a placeholder UIView that will become our reusable AutomatedScrollView control in a subsequent section, while the other UIView will occupy the rest of the screen (above the scrolling area) and give us a place to add a UISwitch to control scrolling later on. The reusable control can be configured in any given containing UIView according to requirements, since it is designed to size itself based on the space given to it in the containing view. I’ve chosen to put it on the bottom of the screen for this tutorial which is the same way I configured it for my 1Goal app.

By default MainViewController.xib is setup for Auto Layout and Size Classes. We’ll be adding some constraints for Auto Layout in this section so our app can accommodate any device and orientation.

Start by dragging two UIView objects onto the canvas, one above the other. For now, temporarily change the background colour so that the top one is red and the bottom one is green. This will just make it easier to see what is going on as we define constraints for Auto Layout. We’ll change the colours later.

In the view hierarchy, modify the names of the View objects from the default, so they are TopView (the red one) and AutomatedScrollView (the bottom green one). This will help make it easy to see how the constraints are structured between the UIView objects.

You should be seeing something like the following depending on how you’ve sized your two UIView objects. Don’t worry if yours are different sizes, as their size/location is arbitrary at this point and we’ll clean it up.

Screen Shot 2015-03-01 at 4.42.33 PM

Now we need some constraints added so that our scrolling message view will be on the bottom of the screen, with the other view occupying the rest of the space on top. Lets start by setting up the following:

  • Pin the UIView for the scrolling area to the Superview leading, trailing, and bottom.
  • Pin the other “top” UIView to Superview leading, trailing, and top.
  • Pin the top of the scrolling UIView to the bottom of the top UIView.

I’m assuming some familiarity with how to use Auto Layout and define constraints, but in case you are fairly new to the concepts, when you have one UIView selected, you can use Editor > Pin > Leading Space to Superview to get startedand then follow the same kind of pattern for the other constraints in relation to the Superview.

For pinning the top and bottom views, Ctrl – drag from the AutomatedScrollView to TopView, and select Vertical Spacing.  Click on the constraint created, and make sure the Size Inspector shows AutomatedScrollView.Top is equal to TopView.Bottom, then edit the Constant to be 0, which tells Auto Layout that there should be no space between the views.  Be sure to enter a Constant = 0 for all the pin constraints.

The final constraint is to set the desired height for the AutomatedScrollView. We’ll use size classes so the height is different for Compact and Regular size widths. Create a height constraint using Editor > Pin > Height, and set the value to 35. Look at the constraint in the Size Inspector, and lets update it to define specific heights for Compact/Any Height, and Regular/Any Height. To accomplish this, click the + sign next to Constant, choose Compact Width/Any Height and enter 35, then click the + sign again and choose Regular Width/Any Height, and enter 90.  Make sure everything is saved.

Your frames won’t match the constraints entered at this point, so to reposition the views based on the constraints, select the root View, then Editor > Resolve Auto Layout Issues > All Views > Update Frames. This will change the sizes of the frames for the two UIView objects so they adhere to the constraints created and the Constant = 0 between the relevant views.

With the above constraints in place Auto Layout has what it needs so there is no ambiguity, and the constraints defined will ensure that the scrolling area height remains consistent regardless of orientation, while the top UIView will occupy the rest of the space, and thus will vary in height. You should now be seeing your view rendering looking like the screenshot below.

Screen Shot 2015-03-01 at 5.12.10 PMNote:  I’ve shown the Height Constraint as well so you can see what the two sizes look like for our previous step. If your views do not match the screenshot and seem misaligned, look at all the Constant values and make sure they are all set to 0.

You can run your app in the simulator now to verify that it looks as expected based on the rendering in IB.

Create AutomatedScrollView UIView With Xib

With our main view in place waiting for the reusable automated scrolling control, it is time to begin implementing this control. The next set of steps to create the initial reusable UIView will be familiar to many readers, but we’ll walk through them for anyone following along that is wanting to learn the techniques with this tutorial. We’ll be creating a child of UIView (.m and .h files), as well as the corresponding Xib file where we’ll design the UI.

Create the child of UIView using File > New > File > iOS > Source > Cocoa Touch Class, then click Next. Enter AutomatedScrollView for the Class. Make sure the Subclass of is UIView. Click Next and then Create. You will see the

To create the corresponding Xib file for our new AutomatedScrollView.m and AutomatedScrollView.h, use File > New > File > iOS > User Interface > View, and click Next. Name the file AutomatedScrollView and click Create.  You’ll now see the AutomatedScrollView.xib file. Now we actually have all the files that are needed for this project, so we’ll continue to define the content.

Configure the AutomatedScrollView Xib Objects and Constraints

Referencing the diagram which described the scrolling background and logic, we want the reusable AutomatedScrollView to be a custom UIView that contains a UIScrollView, which has a content view that was referred to as labelContainerView. This content view is where UILabel instances will be added corresponding to the message to be scrolled automatically.

Before starting to add objects to the root View, click on the View and under Attributes Inspector, look for Simulated Metrics and change the Status Bar value to be None. We don’t want a status bar on our reusable control.

Note:  It is common to also change the Size to Freeform instead of Inferred.  This isn’t necessary for this project since we won’t be placing various elements on the screen that we want to align and see clearly.  However, you can change it to Freeform if you like so that the view fits nicer on the screen. I’ll leave it as Inferred as I work through this tutorial. The setting you choose does not affect the functionality; it is specifying how to display it in IB.

Drag a UIScrollView and place it under the root UIView in the AutomatedScrollView.xib UI. Next, drag a UIView and place it under the UIScrollView. Make sure in each case the object added to the canvas is under the other object in the hierarchy, and not at the same level. Edit the names of these objects on the canvas so they are ScrollView and LabelContainerView.

Ctrl-drag from ScrollView to the root View, and select Leading Space to Container.  Repeat and add constraints for Trailing, Top, and Bottom so the UIScrollView fills the space for the reusable control. Repeat the same constraints between the LabelContainerView and ScrollView, so in other words, Ctrl-drag from LabelContainerView to ScrollView and select the same set of 4 constraints. Over in the Size Inspector, verify that Constant = 0 for all the above constraints.

At this point you will see a red arrow indicating that there are issues with the constraints. The UIScrollView does not have enough information to know what area it should scroll over, or in other words, its contentSize. We’ll fix that with a couple of steps.

Click on LabelContainerView, then select Editor > Pin > Width. Over in the Size Inspector, change the value (should start at 600) for Constant to be 5000. This is the value that will create a large area over which to scroll horizontally, so that it is much wider than the actual screen width and thus can accommodate a reasonably large message, but still tile them one after the other so scrolling appears to be continuous and automated.

Since we’ll be using the reusable control in our main view, or in views from any other apps, let’s add another constraint to make the height of LabelContainerView and ScrollView the same. Ctrl-drag from the LabelContainerView to the ScrollView, and select Equal Heights. With this in place, the red arrow should disappear because we’ve now removed the ambiguity concerning the height and width of the contentSize. Although contentSize height is not explicitly set, the ScrollView and LabelContainerView will always maintain the same height value, which is tied into the height of the root View.

There should still be a yellow arrow indicating something needing to be adjusted between constraints and rendered objects. If not, everything is good but depending on the order constraints are added, likely the frame of the LabelContainerView is not rendered based on the width we gave it of 5000. If so, select the root View, then Editor > Resolve Auto Layout Issues > All Views > Update Frames. This will update the rendered frame for LabelContainerView to be 5000, and all warnings should now be resolved. Make sure everything is saved.

One last step in for the definition and layout of the reusable view is to make the background colour of the scrolling area. This means we need to set the colour of the LabelContainerView since it will occupy the full vertical and horizontal visible area of the UIScrollView. With LabelContainerView selected, go to the Attributes Inspector, and for Background, select a nice shade of blue, for example select Other … > Color Palettes > Crayons > Aqua. A white scrolling message looks nice against this colour.

Configure Xib Custom View to Bind To UIView Object

The new Xib file needs to know what class it will be the UI for. Click on AutomatedScrollView.xib and then File’s Owner. Show the Identity Inspector, where you should see NSObject for Class under the Custom Class section. This step is very important, so be sure you have not selected the root View (in which case you would see UIView as the Class under the Custom Class section).

Under Custom Class, select AutomatedScrollView for the Class value. Xcode presents a list of possible classes which includes any that are user defined. You can see screenshots for this action below, starting with how it originally looks, then choosing the new value, and finally the end result.

Screen Shot 2015-03-03 at 2.43.49 PM
Screen Shot 2015-03-03 at 2.44.33 PM
Screen Shot 2015-03-03 at 2.44.58 PM

Now that we have defined the class for which connections will be made to the Xib archived objects, we can proceed to the next section where we’ll define the IBOutlet properties for the connections in AutomatedScrollView.m so that we can control and modify the UI elements from code.

Configure IBOutlets to Access the Xib UIView in Code

So far we have the AutomatedScrollView.xib which will be a custom UIView, and we have the AutomatedScrollView.m which also represents a UIView instance.  Loading of the Xib creates a UIView that must be added to the instance of  AutomatedScrollView.m ( which is also a UIView). The result of this will be the UIView child AutomatedScrollView.m containing the UIView that is created from loading AutomatedScrollView.xib. This is a subtle point and sometimes it is assumed that there is only one UIView between the Xib and the .m file, but there are two. In the next section, we’ll see this in action as we add the UIView for the Xib as a subview of self in AutomatedScrollView.m. However, first let’s configure IBOutlet properties for objects in the Xib.

Start with the  root UIView. We need to have an IBOutlet for it in AutomatedScrollView.m so that when the Xib loads, we can access the loaded UIView and add it as a subview. Make sure the AutomatedScrollView.m is displayed in the Assistant Editor, and then click the Xib file. Add the following to the .m file above the @implementation:

Ctrl-drag from the root View over to the @interface area, and in the popup window enter view as the Name to create an IBOutlet in code, leaving other values defaulted. The two screenshots below illustrate what you’ll see if you are not familiar with it already.

Screen Shot 2015-03-03 at 3.23.47 PM
Screen Shot 2015-03-03 at 3.24.10 PM

Do the same for the ScrollView, and set Name to scrollView. Finally, repeat again for the LabelContainerView, setting the Name to labelContainerView.

Before we move on, configure AutomatedScrollView.h to be a UIScrollViewDelegate, via the following in the .h file, since we’ll need to react to scrolling.

Load AutomatedScrollView UI From Xib 

If you run the app now, nothing has changed because AutomatedScrollView.m doesn’t actually load the Xib yet, and also we have not told MainViewController.xib that it has anything but a plain UIView for the scrolling area. We’ll address the main screen in the next section.

As described in the previous section, we need to load the AutomatedScrollView.xib and the UIView created from it needs to be added as a subview to AutomatedScrollView.m, or in other words, to self in the .m file.

Add the following code to AutomatedScrollView.m and we’ll walk through what it is doing.

There are two different methods implemented to load the Nib file. initWithCoder is the one that will be used in our project since it is called when one Xib loads another, but as a matter of practice, I like to implement initWithFrame as well. When using IB_DESIGNABLE design time live rendering of custom components, it is worth noting that IB uses the initWithFrame method to load. At the end of this article, I’ll discuss briefly IB_DESIGNABLE and in fact there is a bit of code in the above which is there specifically for this future functionality.

These methods are quite standard, but in initWithCoder we are calling super, then loading the AutomatedScrollView.xib (but the .xib is inferred), then calling the common setup method. In initWithFrame, the preprocessor macro determines which code runs to load the bundle based on whether it is IB making the call (TARGET_INTERFACE_BUILDER) or a standard call. IB cannot load from mainBundle hence this macro is required.

In the setup method, setTranslatesAutoresizingMaskIntoConstraints:NO is important because we don’t want our loaded UIView to have additional constraints created, given that we’ve already setup all the constraints that Auto Layout needs. The [self addSubview:self.view] is where we add the UIView loaded from the Xib as a subview of self, or in other words, the AutomatedScrollView child of UIView.

There is one more method, setupConstraints, which is discussed in the next section.

Additional Constraints Between UIViews

This next step isn’t obvious, but we need to create constraints between the UIView child we’ve defined as AutomatedScrollView.m, and the contained UIView that was loaded from the Nib. If we didn’t, then Auto Layout would not know the layout relationship between these two objects while performing the layout. These need to be done in code after Nib loading since there is no way to do them visually. We want the UIView loaded from the Nib to completely fill the AutomatedScrollView.m UIView, so we need constraints defined in the usual fashion to pin the contained view (subview) to the Superview (self) leading, trailing, top, and bottom. These are the four constraints that are defined in the setupConstraints method, which executes after we’ve added the subview.

Change MainViewController.xib to Use AutomatedScrollView Control

Although we haven’t implemented the scrolling and related logic yet, let’s update MainViewController.xib so that instead of having a plain UIView at the bottom of the screen, it is the reusable AutomatedScrollView control.  Once we do that we can run the app and see that the custom control is at the bottom of the main screen based on the background blue colour defined earlier.

Click on MainViewController.xib and select the view element that we previously named AutomatedScrollView. In the Identity Inspector, where it says UIView for the Class value, select AutomatedScrollView from the drop-down.  We’ve now specified that the UIView at the bottom of the main screen is the reusable control we’ve been working on.

Save and then run the app.  You should see the blue area at the bottom of the screen, like this screenshot to the right.
Screen Shot 2015-03-03 at 9.45.37 PM

While we’re involved with MainViewController.xib and seeing the colours of the running app, lets revert the background colours we specified earlier in the main view.

With MainViewController.xib selected, select TopView in the editor view hierarchy. In the Attributes Inspector, change Background to a light gray colour. I have chosen to make it an RGB colour of 239, 239, 244 since this is a light gray used in some Apple apps. You can choose RGB using Other… > Color Sliders > RGB Sliders, and then enter the three values, as shown on the right.
Screen Shot 2015-03-03 at 9.55.51 PM

We’ve already seen that the green colour we originally specified for the Background of the lower UIView on the main screen is now blue since we’ve specified the reusable view. For completeness, let’s remove the green colour of the AutomatedScrollView element. Select the AutomatedScrollView in the view hierarchy, and change Background to Default. The only difference we’ll see is in the rendering of the view in IB, where green will change to white. When the app is run, it is still the blue specified in AutomatedScrollView.xib.

It is now looking like the screenshot we started with, without the scrolling message, and also without the switch and label text.

Scrolling Control and Timing

The last several sections have focused on creating a reusable view and integrating it into the main view. We’ll now start implementing the logic needed for the automated scrolling features of the app.

To get started, a few properties are needed in AutomatedScrollView.m. Add the code below to this class below the IBOutlet properties that are currently defined.

The timer and visibleLabels properties are used by the scrolling logic, while the labelText is used for storing the colour of the scrolling message text.

We need to implement methods to control the automated scrolling. In AutomatedScrollView.m, add the code below under the setupConstraints method.

The doHorizontalScrolling  method creates a timer and gives it the doSingleScroll callback method to be called when the timer fires. doSingleScroll is the method that changes the contentOffset of the UIScrollView to achieve the message movement on the screen. stopTimer stops and removes the timer to cease the scrolling message. removeAllLabels is used to empty the array that holds instances of UILabel that contain the message text.

Label Tiling

Before we look at label tiling, add the code below to AutomatedScrollView.h.

The labelTextColor property is used by the tiling logic to obtain the colour that the scrolling message labels should be set to.  We don’t have to put this in the .h file, but I did originally to implement the live rendering and property editing with IB_DESIGNABLE and IBInspectable, so let’s leave it in the header file.

In the scrolling code we defined in the previous section, as the contentOffset is changed such that the visible area of the labelContainerView is moved, tiling logic checks to see whether another label needs to be added to the labelContainerView on the right and left, so that there is always message text over which to scroll. Periodically the visible area is recentered within the contentSize of the UIScrollView so that the movement of the visible area never reaches the end of the contentSize.  When this happens, labels usually need to be added to the left and/or right of the set that are already being scrolled, depending on the size of the message being scrolled and the orientation/size of the screen.

In AutomatedScrollView.m, add the tiling related code below.

During the subview layout, which we’ll cover in the next section, tileLabelsFromMinX:(CGFloat)minimumVisibleX toMaxX:(CGFloat)maximumVisibleX is called to add or remove UILabel instances as required so that there is always message text being scrolled within the visible area of the labelViewContainer. The placeNewLabelOnRight and placeNewLabelOnLeft methods both use insertLabel to add a new UILabel subview to the labelContainerView. Labels added to the right are added to the end of the visibleLabels array by  placeNewLabelOnRight, and labels added to the left are added to the beginning of the visibleLabels array. The visibleLabels array is used during recentering logic to iterate the UILabel instances and move them the same amount as the visible bounds is moved.  Moving the UILabel instances hides the fact that the visible area has actually been moved, because from the users perspective scrolling has simply continued and the re-centering and moving of labels is not discernible.

When inserting a UILabel, properties are setup for the label, and each label is assigned a width that is a little wider than the text to achieve visibly appealing message separation during scrolling. Note the check to see if the app is running on an iPad, and if it is, the font size is increased from the default value so it is proportional to the larger scrolling area which was defined in the Xib file for Regular width.

Layout and Re-centering

In AutomatedScrollView.m, define the methods below.

These two methods are central to the continuous scrolling capability.  Before discussing the details, add two more methods as illustrated below.  Add them directly below the setupConstraints method if you want the #pragma mark to flow nicely since awakeFromNib is part of initialization.

Now onto some description of what we’ve just defined.  awakeFromNib is called after the UIView is loaded from the Nib. In this method we setup a default scrolling message and colour, then initialize the array to hold labels that will be scrolled, and finally, add self as the delegate of the UIScrollView so that we receive a callback each time there is a programmatic scrolling increment.

In the definition of the delegate method scrollViewDidScroll we trigger a layout of subviews. It is important to trigger it this way as calling layoutSubviews directly is highly discouraged.

Each time there is a scroll, layoutSubviews will be called, and there is a check to see if it is time to re-center the visible bounds by changing the contentOffset. This is done by comparing where the current contentOffset is in relation to how far off center it should be for the visible bounds to be centered in the contentSize width. If contentOffset has moved 25% of where it should be in relation to the middle of the contentSize, then it is time to recenter the visible area by moving the contentOffset.  The value of 25% is somewhat arbitrary and could be modified.

If recentering is performed by changing the contentOffset so that the visible area is centered, then the set of labels is also moved by the same amount, as mentioned earlier, to hide the fact that we’re doing some behind the scenes movement to facilitate continuous scrolling. Being able to iterate the labels to move them is accomplished by having the array of labels that have been added as subviews of labelContainerView.

Before starting the recentering process, scrolling is stopped while the manual movement of the contentOffset and labels is taking place, and in the case it was stopped there is a BOOL that denotes it should be restarted to continue scrolling from the new centered contentOffset.

We have enough setup now such that you can run the app and see the default message scrolling at the bottom of the screen.

Reusable Control Public Interface Methods

In MainViewController.m we want to be able to import only the .h file for the reusable control.  We want some methods exposed in the header file that are available to a class that uses the control and may want to do some setup, customization, or control. In our case we’d at least want to be able to start and stop scrolling, and perhaps set the banner colour, which is the background colour of labelContainerView that we’ve set to blue.

In AutomatedScrollView.h, add the three method declarations below.

The implementation of these methods will allow a class to interact with the reusable control. In AutomatedScrollView.m, add the method definitions as shown below.  I’ve added them below the other methods, just before @end.

Despite having these methods defined, we still can’t do anything with them from MainViewController.m. Remember that so far the reusable control is only referenced in the MainViewController.xib file, but we do not yet have an IBOutlet  for it such that we can send it messages.  Let’s define what we need.

In MainViewController.m, add an import statement for AutomatedScrollView.h.

Alt-click MainViewController.m so it is in the Assistant Editor and we can drag from the Xib file to create an outlet.  Select the MainViewController.xib, and Ctrl-drag over to below the @interface in MainViewController.m. When the pop-up appears, enter automatedScrollView for the Name, and leave Connection as Outlet, then click Connect. Here is what it looks like when you enter the data in the pop-up.

Screen Shot 2015-03-05 at 5.44.08 PM

This creates the IBOutlet so that we can connect to the reusable control, and specifically, to the methods we defined earlier.

In MainViewController.m, add the code below in viewDidLoad , after the [super viewDidLoad].

Save and then run the app, where you should see it looking like the screenshot on the right.  We’ve started the scrolling with a custom message supplied by the main view, and with a colour also specified by the main view.
Screen Shot 2015-03-05 at 5.58.33 PM

Lets comment out the line that sets the banner colour, now that we’ve seen the pattern. Run again and it should be back to the blue we set earlier, but with the new message that is being set from MainViewController.m.

Switch For Scrolling Control From Main Controller

As an additional feature, we’ll add the ability to start and stop scrolling with a switch on the main view, and we’ll add a descriptive title for the app as well so it looks a little nicer.  We’ve reached our goal of building and using a reusable control already, so if you want to skip this section and the next, feel free to do so.  Otherwise, follow along as we add a couple of other features.  In the next section we experiment with the live rendering and property editing for embedded view controls.

For this section, I won’t go into as much detail as we have thus far in terms of using Xcode to create and wire up view objects.

Select MainViewController.xib and drag a UILabel onto the middle of the top view.  Change the default Label value to Automated Scrolling Message App. Click the + next to Font, and select Compact Width/Any Height.  Leave the default value, click + again, and select Regular Width/Any Height.  Change the value to 30. We’ve increased the font size so it will look proportionate on an iPad.

With the label selected, create a constraint with Editor > Align > Horizontal Center in Container, and do the same for vertical.  Click the root View, and resolve the auto layout issues with All Views > Update Frames.  The label looks correct now.

Drag a UISwitch to the canvas a comfortable distance below the label, and try and drop it about center.  Ctrl-drag from the switch to the label (in canvas or from the outline view hierarchy), and select Vertical Spacing. With the switch selected, select Editor > Align > Horizontal Center in Container and now auto layout is happy.

Now we need to wire the UISwitch up to the main view, and we need an outlet and action.  With MainViewController.m in the Assistant Editor, Ctrl-drag from the UISwitch over to create an IBOutlet, and set Name to switchView. Ctrl-drag again to create an IBAction, by setting Connection to Action, and enter switchPressed as the Name.

A method has been added to the bottom of the class.  Insert the following code in the method.

We’ve added logic to start and stop the scrolling based on the switch, so save and run the app. The initial scrolling message is the value that we set from the viewDidLoad method.  Click the switch to stop scrolling and clear the text.  Click again to start.  Now the message is the value that is set in the code we just added to respond to the switch being enabled.

That was quick, but now we’ve seen the ability to add other controls and interact with the reusable control we have implemented.  If you ran on iPhone this time, try it on the iPad and vice versa.  You should notice the change in font.

Live Rendering And Property Editing For Reusable UIView

As I mentioned earlier in this article, originally I had implemented this project to use IB_DESIGNABLE and IBInspectable so that the reusable AutomatedScrollView would render in the main UIView (showing the background colour), and also facilitate exposing properties in IB for editing just like any other properties in Xcode (for example the message text colour). However, it turns out that there is seemingly a limit as to how wide a control can be without causing issues rendering the embedded view.

For this project, the width of the labelViewContainer (for a wide contentSize on the UIScrollView) is well beyond the apparent range. I have not investigated this in detail to determine any additional specifics.

Using AutomatedScrollView in Your Own Apps

You are free to use AutomatedScrollView in your own apps at your own risk. To do so, simply copy the AutomatedScrollView folder from the GitHub source into your own project, and add the files to Xcode, remembering to select “Create Folder References” when asked by Xcode. Alternatively, if you’ve followed along and built your own AutomatedScrollView, you can use the three AutomatedScrollView.* files within any folder of your own project according to your typical project structure.

If you have comments, suggestions, improvements, or any general feedback, feel free to leave a comment or contact me by email.

Leave a Comment: