- Original link: Swift programming 101:creating self-registering Swift UI Controls
- Original Author: Kevin McNeish
- Development technology Front www.devtf.cn
- Translator: Kmyhy
- Reviewer: lastday
- Status: Complete
For custom controls, how do you respond to event notifications without destroying the original message mechanism? In this article, I'll demonstrate a notification proxy class that, with a simple example, adds its own new functionality to an existing iOS UI control: Adding placeholder text to the text view control.
Problem: Missing placeholder
Placeholder text is a good way to prompt users to enter data of a specified type in some controls. The placeholder property of the Uikit Uitextfield control is used to do this. For example, in the Twitter options settings, the User name field uses the placeholder text. With this placeholder text, users can know where to enter a Twitter username that contains the @ symbol. The placeholder text in the password field indicates that the field is required.
Figure 1-Placeholder text in the Setup program
Although the text filed has a placeholder property, its sibling control, text view, does not have this property.
Solution to the problem
I'm going to solve the problem this way:
- Create an Uitextview extension to add a placeholder computed property
- In the extension, when no text is entered in the TextView, a label is displayed, and if the input has text, the label is hidden.
As I mentioned in the previous article, I prefer to use extensions rather than subclasses. Because the extension allows me to use "out of box" Uikit controls in the app. All I need to do is add a class extension file to the project, and the class will automatically get the new feature.
Way 1:uitextviewdelegate
iOS has several ways to inform your app when users enter text in TextView. One is through the Uitextviewdelegate protocol. In this extension, there is a reference to TextView stored in its own delegate property. When the user enters or deletes a character, the TextView protocol method is called. We can add code that hides and displays the placeholder tag in the protocol method.
The disadvantage of this workaround is that the Text view is too dependent on the delegate property because you can only register a delegate object in a Uicontrol. If you need to add more delegate objects to the TextView, you'll be in trouble.
Way 2:nsnotificationcenter
Nsnotificationcenter the uitextviewtextdidchangenotification notification to tell you that some characters were entered or deleted by the user in TextView. This is a better choice because it is no longer dependent on the delegate property. The disadvantage is that you need to log off to the notification hub. In general, we unregister the object in the Deinit method of the object to Nsnotificationcenter. However, in swift, we cannot use the Deinit method in the extension. So how can we break this limit?
Create a notification agent
By creating a lightweight proxy object to break this limit, this proxy object replaces TextView to register with the notification hub.
I have created a uitextview extension and a proxy class in my project that you can download from here.
Double-click the. xcodeproj file to open the project with Xcode. Select the Mmtextviewextensions.swift file in the Project Navigator window and you will find this notification proxy class (as you can see, which also contains the Mmdyamictypeextensions class in the previous article).
The following is the notification proxy class located at the head of the file:
As you can see, it is the UIView subclass. This allows us to add it as a subview to the TextView. Addobserverforname:usingblock: Method notifies the hub that the method has the same signature. The only line of code in this method is to register the TextView with the notification hub and pass the parameters past, including the TextView closure, so that the closure is executed when the notification occurs. The notification center returns a Nsobjectprotocol object that we will use later to log off the notification.
The Deinit method also has only one line of code, which simply unregisters the object to the notification hub.
Notifies the proxy class to be reusable. You can use it for any type of notification and any type of object that you want to receive notifications about.
Then there is the extension of Uitextview, which has a Placeholderlabel attribute in the extension, which, as you would expect, refers to a placeholder tag object.
There is also a placeholder string property. In the back you will see that all the miracles will occur at run time, and when the placeholder property is set, the code for this computed property will be executed.
Now open the Main.storyboard file. As shown in 2, there is only one scene in the storyboard, at the top of the scene, there is a text View.
Figure 2-The main scene contains a text view
When you select text View and then open the Properties panel, you will see a placeholder property, which is an added attribute in the extension, and the default value for this property is "Enter your text here!". This text is not displayed at design time (to be visible at design time, we need to spend a lot of work, so this is not the subject of this article), but it will be displayed at run time.
The Notification proxy at run time runtime notification agent
The UML sequence diagram in Figure 3 shows the order in which message delivery occurs between all objects.
Figure 3-sequence of message passing between objects at run time
The explanations for each step are as follows:
- When the Uitextview placeholder text is changed at run time, the code in the placeholder computed property of the extension is triggered.
- The extended Addplaceholderlabel method is called.
- The Addplaceholderlabel method creates a placeholder label and sets the label text.
- The placeholder tag is added to the Uitextview.
- A notification proxy object was created.
- The extension invokes the Addobserverforname:withblock: method of the notification agent and specifies an interest in uitextviewtextdidchangenotification notifications. The closure code is also executed when the notification occurs.
- Notifies the proxy object to register Uitextview to the notification hub while passing the notification time to TextView, and when the notification occurs, Uitextview's closure code is executed.
- Uitextview adds the notification proxy object as a subview.
- When the uitextviewtextdidchangenotification notification occurs, the notification hub calls the TextView extension's closure.
- The Uitextview extension sets the hidden property of the placeholder label to true and false, depending on whether the text in the TextView has content.
11. When TextView is deconstructed at run time, both the placeholder tag and the notification proxy object are deconstructed.
- When the notification proxy object is deconstructed, the TextView object is unregistered from the notification center.
Let's take it for a test run! run tests
In Xcode ' s Scheme control, select one of the simulators such as IPhone 6.
In the Scheme drop-down list of Xcode, select an emulator, such as IPhone6.
Click Xcode ' s Run button.
Click the Run button for Xcode.
When the app is appears in the Simulator, you can see the placeholder text (Figure 4).
When the app runs in the emulator, we can see the placeholder text (Figure 4).
Figure 4-placeholder text at run time
4.Now type some code in the text view. As soon as you begin typing, the placeholder label disappears (Figure 5).现在在TextView中输入任意字符。此时,placeholder将消失(图5)。
Figure 5-placeholder the text disappears
If you delete the entered characters cleanly, the placeholder text will appear again.
Conclusion
There are many ways to solve programming problems. The best way to do this is to look at your current choices and then analyze the pros and cons one after the other. I hope you can see the benefits of the sequence diagram in this article. It allows you to draw the interaction between objects at run time. I also used this method when I was writing code. You'll find that they can help you identify potential problems and help you find new and more efficient solutions to your programming problems.
Create a self-registering swift UI control