2

I'm building a CustomTextField View and wanting to add view modifiers.

Using the standard .modifier(CustomViewModifier) is working just fine. Now I want to build ViewModifier functions so that I can use my modifiers just like any other SwiftUI modifiers.

In my CustomTextField, I've got multiple methods like this:

func setCustomPlaceholder(placeholder: String = "Enter Text") -> some View {
        modifier(CustomTextFieldPlaceholderViewModifier(viewModel: viewModel, placeholder: placeholder))
    }

These methods work. However, I can only use one of these methods at a time.

I've read several articles and this thread. Because I don't want these modifiers available to any View, I'd like to avoid using an extension to View.

In this thread, one of the answers used an extension to Text. So I tried placing my modifier methods into an extension to my CustomTextField. However, I'm still facing the same issue. The View is only recognizing one modifier function at a time.

This is how I'm using it:

VStack {
            CustomTextField()
                .setCustomPlaceholder()
                .setBorder()
        }

If I use only one of the modifier methods at a time, it works.

How can I get the functionality I'm looking for? Do I need to build a Protocol and make my CustomTextField conform to it? Thanks for any help!

5
  • “I'd like to avoid using an extension to View“ why’s that? Commented Jun 3, 2022 at 23:15
  • The whole sentence explains it: "Because I don't want these modifiers available to any View, I'd like to avoid using an extension to View." Edit for further explanation: These modifiers are specific to my custom text field. It would be bad practice to expose them to other views. Commented Jun 3, 2022 at 23:19
  • “It would be bad practice to expose them to other views.” Only if they’re not applicable to other views (are they?), not simply if you don’t immediately need it. If you do need to narrow it down, you’ll have to use a protocol to describe the result of your modifiers. I think you can do some View & YourProtocol Commented Jun 3, 2022 at 23:28
  • They are not applicable to other views. Well, ultimately, some of them are, but some aren't. As I refactor this I'll separate them out as needed. Right now, I'm just trying to figure out how to get these available to my specific view only. Because Protocols can inherit from each other, can I build a protocol that inherits from View? Then make my custom view conform to that protocol? Commented Jun 3, 2022 at 23:33
  • 1
    “Because Protocols can inherit from each other” they actually can, but it’s not called inheritance. Though idr if making your protocol derive from View is practical (or a good idea). In my previous comment, I suggested you use protocol composition. The idea is that you’d define your operators on some protocol YourProtocol. Then you make your modifiers return some View & YourProtocol, communicating to your compiler that the result doesn’t just support the methods on View, but also the methods on your new protocol. Commented Jun 4, 2022 at 4:13

2 Answers 2

2

We can just make needed modifiers as our view member functions, which return own type to be called sequentially.

Here is a main part. Tested with Xcode 13.4 / iOS 15.5

struct CustomTextField: View {

    // ... other code

    func setCustomPlaceholder(placeholder: String = "Enter Text") -> Self {  // << here Self !!
        var tmp = self
        tmp.placeholder = placeholder
        return tmp
    }

    // ... other code
}

Complete code and demo in project

Sign up to request clarification or add additional context in comments.

Comments

1

If I use only one of the modifier methods at a time, it works

That’s because the only thing known about the result of the first view modifier is that it returns a View (of an unspecified kind).

Since you haven’t defined your view modifier on View… you can’t call it on a View.

1 Comment

Ah! Makes sense. Can I just return my specific view from those functions? How can I do this without using a View extension?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.