@objc and private methods


(Tod Cunningham) #1

I wanted to get thoughts on the use of @objc and private methods. Should this usage be avoided or leveraged?

I have seen some code where things like UIButton and Gesture recognizer handlers are defined as being private. I would have thought this would result in a compiler error given objective-c doesn’t support private accessors. However, it compiles and works as expected (kind of).

One plus for defining the handlers as private is they aren’t visible to swift outside of the file they are defined in. The problem is you can run into some issues with inheritance if you define the same handler in a derived class. Take the following simple example:

class Test {
    @objc private func somefunc() {
        print( "hello 1" )
    }
}

-- in another file –

class Test2: Test {
    @objc private func somefunc() {
        print( "hello 2" )
    }
}

This will result in the following compiler error:

Method 'somefunc()' with Objective-C selector 'somefunc' conflicts with method 'somefunc()' from superclass 'Test' with the same Objective-C selector

That error makes sense in an Objective-C context as Test2 has two different methods defined with the same objective-c selector (somefunc). Swift can tell them apart as they are private to each class, but Obj-C can’t tell them apart as they have the same selector thus the error.

One workaround would be to give the method a different Objective-C names such as @objc(test2_somefunc); however, that could really lead to some unexpected results depending on what selector is used to call somefunc. Test2 would need to “register” a different selector for somefunc then Test does for whatever is calling it on the Objective-C side (yuck!).

This can of course be solved by not making the method private which allows Test2 to explicitly override somefunc.

class Test {
   @objc func somefunc() {
       print( "hello 1" )
   }
}

-- in another file –

class Test2: Test {
   @objc override func somefunc() {
       print( "hello 2" )
   }
}

I would say that when declaring @objc methods they shouldn’t be private and should have the same (public/internal) access method as their containing class. What’s your thoughts? Why does swift allow a method to be declared as both @objc and private?

Thanks,


(Zhao Xin) #2

I think @objc makes the function an Objective-C function, so the private is
no longer making the function private in Swift way, but in Objective-C way.
In C++, sub-class can call super-class's private method. What you have to
do is to override the function.

class Test {

    @objc private func somefunc() {

        print( "hello 1" )

    }

}

class Test2: Test {

    @objc override private func somefunc() {

        print( "hello 2" )

    }

}

Zhaoxin

···

On Thu, Jul 21, 2016 at 10:25 PM, Tod Cunningham via swift-users < swift-users@swift.org> wrote:

I wanted to get thoughts on the use of @objc and private methods. Should
this usage be avoided or leveraged?

I have seen some code where things like UIButton and Gesture recognizer
handlers are defined as being private. I would have thought this would
result in a compiler error given objective-c doesn’t support private
accessors. However, it compiles and works as expected (kind of).

One plus for defining the handlers as private is they aren’t visible to
swift outside of the file they are defined in. The problem is you can run
into some issues with inheritance if you define the same handler in a
derived class. Take the following simple example:

class Test {
    @objc private func somefunc() {
        print( "hello 1" )
    }
}

-- in another file –

class Test2: Test {
    @objc private func somefunc() {
        print( "hello 2" )
    }
}

This will result in the following compiler error:

Method 'somefunc()' with Objective-C selector 'somefunc' conflicts with
method 'somefunc()' from superclass 'Test' with the same Objective-C
selector

That error makes sense in an Objective-C context as Test2 has two
different methods defined with the same objective-c selector (somefunc).
Swift can tell them apart as they are private to each class, but Obj-C
can’t tell them apart as they have the same selector thus the error.

One workaround would be to give the method a different Objective-C names
such as @objc(test2_somefunc); however, that could really lead to some
unexpected results depending on what selector is used to call somefunc.
Test2 would need to “register” a different selector for somefunc then Test
does for whatever is calling it on the Objective-C side (yuck!).

This can of course be solved by not making the method private which allows
Test2 to explicitly override somefunc.

class Test {
   @objc func somefunc() {
       print( "hello 1" )
   }
}

-- in another file –

class Test2: Test {
   @objc override func somefunc() {
       print( "hello 2" )
   }
}

I would say that when declaring @objc methods they shouldn’t be private
and should have the same (public/internal) access method as their
containing class. What’s your thoughts? Why does swift allow a method to
be declared as both @objc and private?

Thanks,

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


(Tod Cunningham) #3

If Test and Test2 are in separate files, swift doesn’t allow you to do the override as it “can’t see” the definition of the private method in Test.

···

From: Zhao Xin <owenzx@gmail.com>
Date: Thursday, July 21, 2016 at 11:06 AM
To: Tod Cunningham <tcunningham@vectorform.com>
Cc: "swift-users@swift.org" <swift-users@swift.org>
Subject: Re: [swift-users] @objc and private methods

I think @objc makes the function an Objective-C function, so the private is no longer making the function private in Swift way, but in Objective-C way. In C++, sub-class can call super-class's private method. What you have to do is to override the function.

class Test {

    @objc private func somefunc() {

        print( "hello 1" )

    }

}

class Test2: Test {

    @objc override private func somefunc() {

        print( "hello 2" )

    }

}

Zhaoxin

On Thu, Jul 21, 2016 at 10:25 PM, Tod Cunningham via swift-users <swift-users@swift.org<mailto:swift-users@swift.org>> wrote:
I wanted to get thoughts on the use of @objc and private methods. Should this usage be avoided or leveraged?

I have seen some code where things like UIButton and Gesture recognizer handlers are defined as being private. I would have thought this would result in a compiler error given objective-c doesn’t support private accessors. However, it compiles and works as expected (kind of).

One plus for defining the handlers as private is they aren’t visible to swift outside of the file they are defined in. The problem is you can run into some issues with inheritance if you define the same handler in a derived class. Take the following simple example:

class Test {
    @objc private func somefunc() {
        print( "hello 1" )
    }
}

-- in another file –

class Test2: Test {
    @objc private func somefunc() {
        print( "hello 2" )
    }
}

This will result in the following compiler error:

Method 'somefunc()' with Objective-C selector 'somefunc' conflicts with method 'somefunc()' from superclass 'Test' with the same Objective-C selector

That error makes sense in an Objective-C context as Test2 has two different methods defined with the same objective-c selector (somefunc). Swift can tell them apart as they are private to each class, but Obj-C can’t tell them apart as they have the same selector thus the error.

One workaround would be to give the method a different Objective-C names such as @objc(test2_somefunc); however, that could really lead to some unexpected results depending on what selector is used to call somefunc. Test2 would need to “register” a different selector for somefunc then Test does for whatever is calling it on the Objective-C side (yuck!).

This can of course be solved by not making the method private which allows Test2 to explicitly override somefunc.

class Test {
   @objc func somefunc() {
       print( "hello 1" )
   }
}

-- in another file –

class Test2: Test {
   @objc override func somefunc() {
       print( "hello 2" )
   }
}

I would say that when declaring @objc methods they shouldn’t be private and should have the same (public/internal) access method as their containing class. What’s your thoughts? Why does swift allow a method to be declared as both @objc and private?

Thanks,

_______________________________________________
swift-users mailing list
swift-users@swift.org<mailto:swift-users@swift.org>
https://lists.swift.org/mailman/listinfo/swift-users


(Zhao Xin) #4

Then you should file a bug.

Zhaoxin

···

On Fri, Jul 22, 2016 at 1:03 AM, Tod Cunningham <tcunningham@vectorform.com> wrote:

If Test and Test2 are in separate files, swift doesn’t allow you to do the
override as it “can’t see” the definition of the private method in Test.

From: Zhao Xin <owenzx@gmail.com>
Date: Thursday, July 21, 2016 at 11:06 AM
To: Tod Cunningham <tcunningham@vectorform.com>
Cc: "swift-users@swift.org" <swift-users@swift.org>
Subject: Re: [swift-users] @objc and private methods

I think @objc makes the function an Objective-C function, so the private
is no longer making the function private in Swift way, but in Objective-C
way. In C++, sub-class can call super-class's private method. What you
have to do is to override the function.

class Test {

    @objc private func somefunc() {

        print( "hello 1" )

    }

}

class Test2: Test {

    @objc override private func somefunc() {

        print( "hello 2" )

    }

}

Zhaoxin

On Thu, Jul 21, 2016 at 10:25 PM, Tod Cunningham via swift-users < > swift-users@swift.org<mailto:swift-users@swift.org>> wrote:
I wanted to get thoughts on the use of @objc and private methods. Should
this usage be avoided or leveraged?

I have seen some code where things like UIButton and Gesture recognizer
handlers are defined as being private. I would have thought this would
result in a compiler error given objective-c doesn’t support private
accessors. However, it compiles and works as expected (kind of).

One plus for defining the handlers as private is they aren’t visible to
swift outside of the file they are defined in. The problem is you can run
into some issues with inheritance if you define the same handler in a
derived class. Take the following simple example:

class Test {
    @objc private func somefunc() {
        print( "hello 1" )
    }
}

-- in another file –

class Test2: Test {
    @objc private func somefunc() {
        print( "hello 2" )
    }
}

This will result in the following compiler error:

Method 'somefunc()' with Objective-C selector 'somefunc' conflicts with
method 'somefunc()' from superclass 'Test' with the same Objective-C
selector

That error makes sense in an Objective-C context as Test2 has two
different methods defined with the same objective-c selector (somefunc).
Swift can tell them apart as they are private to each class, but Obj-C
can’t tell them apart as they have the same selector thus the error.

One workaround would be to give the method a different Objective-C names
such as @objc(test2_somefunc); however, that could really lead to some
unexpected results depending on what selector is used to call somefunc.
Test2 would need to “register” a different selector for somefunc then Test
does for whatever is calling it on the Objective-C side (yuck!).

This can of course be solved by not making the method private which allows
Test2 to explicitly override somefunc.

class Test {
   @objc func somefunc() {
       print( "hello 1" )
   }
}

-- in another file –

class Test2: Test {
   @objc override func somefunc() {
       print( "hello 2" )
   }
}

I would say that when declaring @objc methods they shouldn’t be private
and should have the same (public/internal) access method as their
containing class. What’s your thoughts? Why does swift allow a method to
be declared as both @objc and private?

Thanks,

_______________________________________________
swift-users mailing list
swift-users@swift.org<mailto:swift-users@swift.org>
https://lists.swift.org/mailman/listinfo/swift-users


(Josh Parmenter) #5

Is this a bug? I think this is more a question of what is best practice.
Best,
Josh

···

On Jul 21, 2016, at 10:48 AM, Zhao Xin via swift-users <swift-users@swift.org<mailto:swift-users@swift.org>> wrote:

Then you should file a bug.

Zhaoxin

On Fri, Jul 22, 2016 at 1:03 AM, Tod Cunningham <tcunningham@vectorform.com<mailto:tcunningham@vectorform.com>> wrote:
If Test and Test2 are in separate files, swift doesn’t allow you to do the override as it “can’t see” the definition of the private method in Test.

From: Zhao Xin <owenzx@gmail.com<mailto:owenzx@gmail.com>>
Date: Thursday, July 21, 2016 at 11:06 AM
To: Tod Cunningham <tcunningham@vectorform.com<mailto:tcunningham@vectorform.com>>
Cc: "swift-users@swift.org<mailto:swift-users@swift.org>" <swift-users@swift.org<mailto:swift-users@swift.org>>
Subject: Re: [swift-users] @objc and private methods

I think @objc makes the function an Objective-C function, so the private is no longer making the function private in Swift way, but in Objective-C way. In C++, sub-class can call super-class's private method. What you have to do is to override the function.

class Test {

    @objc private func somefunc() {

        print( "hello 1" )

    }

}

class Test2: Test {

    @objc override private func somefunc() {

        print( "hello 2" )

    }

}

Zhaoxin

On Thu, Jul 21, 2016 at 10:25 PM, Tod Cunningham via swift-users <swift-users@swift.org<mailto:swift-users@swift.org><mailto:swift-users@swift.org<mailto:swift-users@swift.org>>> wrote:
I wanted to get thoughts on the use of @objc and private methods. Should this usage be avoided or leveraged?

I have seen some code where things like UIButton and Gesture recognizer handlers are defined as being private. I would have thought this would result in a compiler error given objective-c doesn’t support private accessors. However, it compiles and works as expected (kind of).

One plus for defining the handlers as private is they aren’t visible to swift outside of the file they are defined in. The problem is you can run into some issues with inheritance if you define the same handler in a derived class. Take the following simple example:

class Test {
    @objc private func somefunc() {
        print( "hello 1" )
    }
}

-- in another file –

class Test2: Test {
    @objc private func somefunc() {
        print( "hello 2" )
    }
}

This will result in the following compiler error:

Method 'somefunc()' with Objective-C selector 'somefunc' conflicts with method 'somefunc()' from superclass 'Test' with the same Objective-C selector

That error makes sense in an Objective-C context as Test2 has two different methods defined with the same objective-c selector (somefunc). Swift can tell them apart as they are private to each class, but Obj-C can’t tell them apart as they have the same selector thus the error.

One workaround would be to give the method a different Objective-C names such as @objc(test2_somefunc); however, that could really lead to some unexpected results depending on what selector is used to call somefunc. Test2 would need to “register” a different selector for somefunc then Test does for whatever is calling it on the Objective-C side (yuck!).

This can of course be solved by not making the method private which allows Test2 to explicitly override somefunc.

class Test {
   @objc func somefunc() {
       print( "hello 1" )
   }
}

-- in another file –

class Test2: Test {
   @objc override func somefunc() {
       print( "hello 2" )
   }
}

I would say that when declaring @objc methods they shouldn’t be private and should have the same (public/internal) access method as their containing class. What’s your thoughts? Why does swift allow a method to be declared as both @objc and private?

Thanks,

_______________________________________________
swift-users mailing list
swift-users@swift.org<mailto:swift-users@swift.org><mailto:swift-users@swift.org<mailto:swift-users@swift.org>>
https://lists.swift.org/mailman/listinfo/swift-users

_______________________________________________
swift-users mailing list
swift-users@swift.org<mailto:swift-users@swift.org>
https://lists.swift.org/mailman/listinfo/swift-users


(Zhao Xin) #6

My previous reply was not correct.

I think @objc makes the function an Objective-C function, so the private
is no longer making the function private in Swift way, but in Objective-C
way. In C++, sub-class can call super-class's private method. What you
have to do is to override the function.

​@objc makes the function available to Objective-C, but not only
Objective-C. So the function works in both Objective-C and Swift. In Swift,
the private is different from other languages, its scope is the surrounding
​file. That is why the override doesn't work if both classes are separated
in different files.

If the two classes are in the same file, below code also works.

class Test {

    private func somefunc() {

        print( "hello 1" )

    }

}

class Test2: Test {

    override private func somefunc() {

        print( "hello 2" )

    }

}

So the only problem is with @objc and put the two classes into different
files, you can't override the function as it is over-scoped in Swift.
However, you can't use it in the same name either, as Objective-C will find
the function names are conflicts.

So the resolution is either to use it as it is, or to file a bug to
eliminate using @objc and private together as there is no private access
level in Objective-C.

Zhaoxin

···

On Fri, Jul 22, 2016 at 2:22 AM, Josh Parmenter <jparmenter@vectorform.com> wrote:

Is this a bug? I think this is more a question of what is best practice.
Best,
Josh

On Jul 21, 2016, at 10:48 AM, Zhao Xin via swift-users < > swift-users@swift.org<mailto:swift-users@swift.org>> wrote:

Then you should file a bug.

Zhaoxin

On Fri, Jul 22, 2016 at 1:03 AM, Tod Cunningham < > tcunningham@vectorform.com<mailto:tcunningham@vectorform.com>> wrote:
If Test and Test2 are in separate files, swift doesn’t allow you to do the
override as it “can’t see” the definition of the private method in Test.

From: Zhao Xin <owenzx@gmail.com<mailto:owenzx@gmail.com>>
Date: Thursday, July 21, 2016 at 11:06 AM
To: Tod Cunningham <tcunningham@vectorform.com<mailto:
tcunningham@vectorform.com>>
Cc: "swift-users@swift.org<mailto:swift-users@swift.org>" <
swift-users@swift.org<mailto:swift-users@swift.org>>
Subject: Re: [swift-users] @objc and private methods

I think @objc makes the function an Objective-C function, so the private
is no longer making the function private in Swift way, but in Objective-C
way. In C++, sub-class can call super-class's private method. What you
have to do is to override the function.

class Test {

    @objc private func somefunc() {

        print( "hello 1" )

    }

}

class Test2: Test {

    @objc override private func somefunc() {

        print( "hello 2" )

    }

}

Zhaoxin

On Thu, Jul 21, 2016 at 10:25 PM, Tod Cunningham via swift-users < > swift-users@swift.org<mailto:swift-users@swift.org><mailto: > swift-users@swift.org<mailto:swift-users@swift.org>>> wrote:
I wanted to get thoughts on the use of @objc and private methods. Should
this usage be avoided or leveraged?

I have seen some code where things like UIButton and Gesture recognizer
handlers are defined as being private. I would have thought this would
result in a compiler error given objective-c doesn’t support private
accessors. However, it compiles and works as expected (kind of).

One plus for defining the handlers as private is they aren’t visible to
swift outside of the file they are defined in. The problem is you can run
into some issues with inheritance if you define the same handler in a
derived class. Take the following simple example:

class Test {
    @objc private func somefunc() {
        print( "hello 1" )
    }
}

-- in another file –

class Test2: Test {
    @objc private func somefunc() {
        print( "hello 2" )
    }
}

This will result in the following compiler error:

Method 'somefunc()' with Objective-C selector 'somefunc' conflicts with
method 'somefunc()' from superclass 'Test' with the same Objective-C
selector

That error makes sense in an Objective-C context as Test2 has two
different methods defined with the same objective-c selector (somefunc).
Swift can tell them apart as they are private to each class, but Obj-C
can’t tell them apart as they have the same selector thus the error.

One workaround would be to give the method a different Objective-C names
such as @objc(test2_somefunc); however, that could really lead to some
unexpected results depending on what selector is used to call somefunc.
Test2 would need to “register” a different selector for somefunc then Test
does for whatever is calling it on the Objective-C side (yuck!).

This can of course be solved by not making the method private which allows
Test2 to explicitly override somefunc.

class Test {
   @objc func somefunc() {
       print( "hello 1" )
   }
}

-- in another file –

class Test2: Test {
   @objc override func somefunc() {
       print( "hello 2" )
   }
}

I would say that when declaring @objc methods they shouldn’t be private
and should have the same (public/internal) access method as their
containing class. What’s your thoughts? Why does swift allow a method to
be declared as both @objc and private?

Thanks,

_______________________________________________
swift-users mailing list
swift-users@swift.org<mailto:swift-users@swift.org><mailto:
swift-users@swift.org<mailto:swift-users@swift.org>>
https://lists.swift.org/mailman/listinfo/swift-users

_______________________________________________
swift-users mailing list
swift-users@swift.org<mailto:swift-users@swift.org>
https://lists.swift.org/mailman/listinfo/swift-users


(Tod Cunningham) #7

What’s the best practice around using @objc on private methods? While they can be used together, should their use be avoided or embraced?

Thanks,
Tod

···

From: Zhao Xin <owenzx@gmail.com>
Date: Thursday, July 21, 2016 at 10:42 PM
To: Josh Parmenter <jparmenter@vectorform.com>
Cc: Tod Cunningham <tcunningham@vectorform.com>, "swift-users@swift.org" <swift-users@swift.org>
Subject: Re: [swift-users] @objc and private methods

My previous reply was not correct.
I think @objc makes the function an Objective-C function, so the private is no longer making the function private in Swift way, but in Objective-C way. In C++, sub-class can call super-class's private method. What you have to do is to override the function.

​@objc makes the function available to Objective-C, but not only Objective-C. So the function works in both Objective-C and Swift. In Swift, the private is different from other languages, its scope is the surrounding ​file. That is why the override doesn't work if both classes are separated in different files.

If the two classes are in the same file, below code also works.

class Test {

    private func somefunc() {

        print( "hello 1" )

    }

}

class Test2: Test {

    override private func somefunc() {

        print( "hello 2" )

    }

}

So the only problem is with @objc and put the two classes into different files, you can't override the function as it is over-scoped in Swift. However, you can't use it in the same name either, as Objective-C will find the function names are conflicts.

So the resolution is either to use it as it is, or to file a bug to eliminate using @objc and private together as there is no private access level in Objective-C.

Zhaoxin

On Fri, Jul 22, 2016 at 2:22 AM, Josh Parmenter <jparmenter@vectorform.com<mailto:jparmenter@vectorform.com>> wrote:
Is this a bug? I think this is more a question of what is best practice.
Best,
Josh

On Jul 21, 2016, at 10:48 AM, Zhao Xin via swift-users <swift-users@swift.org<mailto:swift-users@swift.org><mailto:swift-users@swift.org<mailto:swift-users@swift.org>>> wrote:

Then you should file a bug.

Zhaoxin

On Fri, Jul 22, 2016 at 1:03 AM, Tod Cunningham <tcunningham@vectorform.com<mailto:tcunningham@vectorform.com><mailto:tcunningham@vectorform.com<mailto:tcunningham@vectorform.com>>> wrote:
If Test and Test2 are in separate files, swift doesn’t allow you to do the override as it “can’t see” the definition of the private method in Test.

From: Zhao Xin <owenzx@gmail.com<mailto:owenzx@gmail.com><mailto:owenzx@gmail.com<mailto:owenzx@gmail.com>>>
Date: Thursday, July 21, 2016 at 11:06 AM
To: Tod Cunningham <tcunningham@vectorform.com<mailto:tcunningham@vectorform.com><mailto:tcunningham@vectorform.com<mailto:tcunningham@vectorform.com>>>
Cc: "swift-users@swift.org<mailto:swift-users@swift.org><mailto:swift-users@swift.org<mailto:swift-users@swift.org>>" <swift-users@swift.org<mailto:swift-users@swift.org><mailto:swift-users@swift.org<mailto:swift-users@swift.org>>>
Subject: Re: [swift-users] @objc and private methods

I think @objc makes the function an Objective-C function, so the private is no longer making the function private in Swift way, but in Objective-C way. In C++, sub-class can call super-class's private method. What you have to do is to override the function.

class Test {

    @objc private func somefunc() {

        print( "hello 1" )

    }

}

class Test2: Test {

    @objc override private func somefunc() {

        print( "hello 2" )

    }

}

Zhaoxin

On Thu, Jul 21, 2016 at 10:25 PM, Tod Cunningham via swift-users <swift-users@swift.org<mailto:swift-users@swift.org><mailto:swift-users@swift.org<mailto:swift-users@swift.org>><mailto:swift-users@swift.org<mailto:swift-users@swift.org><mailto:swift-users@swift.org<mailto:swift-users@swift.org>>>> wrote:
I wanted to get thoughts on the use of @objc and private methods. Should this usage be avoided or leveraged?

I have seen some code where things like UIButton and Gesture recognizer handlers are defined as being private. I would have thought this would result in a compiler error given objective-c doesn’t support private accessors. However, it compiles and works as expected (kind of).

One plus for defining the handlers as private is they aren’t visible to swift outside of the file they are defined in. The problem is you can run into some issues with inheritance if you define the same handler in a derived class. Take the following simple example:

class Test {
    @objc private func somefunc() {
        print( "hello 1" )
    }
}

-- in another file –

class Test2: Test {
    @objc private func somefunc() {
        print( "hello 2" )
    }
}

This will result in the following compiler error:

Method 'somefunc()' with Objective-C selector 'somefunc' conflicts with method 'somefunc()' from superclass 'Test' with the same Objective-C selector

That error makes sense in an Objective-C context as Test2 has two different methods defined with the same objective-c selector (somefunc). Swift can tell them apart as they are private to each class, but Obj-C can’t tell them apart as they have the same selector thus the error.

One workaround would be to give the method a different Objective-C names such as @objc(test2_somefunc); however, that could really lead to some unexpected results depending on what selector is used to call somefunc. Test2 would need to “register” a different selector for somefunc then Test does for whatever is calling it on the Objective-C side (yuck!).

This can of course be solved by not making the method private which allows Test2 to explicitly override somefunc.

class Test {
   @objc func somefunc() {
       print( "hello 1" )
   }
}

-- in another file –

class Test2: Test {
   @objc override func somefunc() {
       print( "hello 2" )
   }
}

I would say that when declaring @objc methods they shouldn’t be private and should have the same (public/internal) access method as their containing class. What’s your thoughts? Why does swift allow a method to be declared as both @objc and private?

Thanks,

_______________________________________________
swift-users mailing list
swift-users@swift.org<mailto:swift-users@swift.org><mailto:swift-users@swift.org<mailto:swift-users@swift.org>><mailto:swift-users@swift.org<mailto:swift-users@swift.org><mailto:swift-users@swift.org<mailto:swift-users@swift.org>>>
https://lists.swift.org/mailman/listinfo/swift-users

_______________________________________________
swift-users mailing list
swift-users@swift.org<mailto:swift-users@swift.org><mailto:swift-users@swift.org<mailto:swift-users@swift.org>>
https://lists.swift.org/mailman/listinfo/swift-users


(Svein Halvor Halvorsen) #8

I usually mark my target-action methods like so:

private dynamic func didTapNext(sender: UIButton)

"dynamic" makes the compiler generate code for dynamic dispatch, that is
runtime message passing, like objc. The "private" part doesn't change that,
it just reduces clutter.

···

2016-07-22 15:18 GMT+02:00 Tod Cunningham via swift-users < swift-users@swift.org>:

What’s the best practice around using @objc on private methods? While
they can be used together, should their use be avoided or embraced?

Thanks,
Tod

From: Zhao Xin <owenzx@gmail.com>
Date: Thursday, July 21, 2016 at 10:42 PM
To: Josh Parmenter <jparmenter@vectorform.com>
Cc: Tod Cunningham <tcunningham@vectorform.com>, "swift-users@swift.org" <
swift-users@swift.org>
Subject: Re: [swift-users] @objc and private methods

My previous reply was not correct.
I think @objc makes the function an Objective-C function, so the private
is no longer making the function private in Swift way, but in Objective-C
way. In C++, sub-class can call super-class's private method. What you
have to do is to override the function.

​@objc makes the function available to Objective-C, but not only
Objective-C. So the function works in both Objective-C and Swift. In Swift,
the private is different from other languages, its scope is the surrounding
​file. That is why the override doesn't work if both classes are separated
in different files.

If the two classes are in the same file, below code also works.

class Test {

    private func somefunc() {

        print( "hello 1" )

    }

}

class Test2: Test {

    override private func somefunc() {

        print( "hello 2" )

    }

}

So the only problem is with @objc and put the two classes into different
files, you can't override the function as it is over-scoped in Swift.
However, you can't use it in the same name either, as Objective-C will find
the function names are conflicts.

So the resolution is either to use it as it is, or to file a bug to
eliminate using @objc and private together as there is no private access
level in Objective-C.

Zhaoxin

On Fri, Jul 22, 2016 at 2:22 AM, Josh Parmenter <jparmenter@vectorform.com > <mailto:jparmenter@vectorform.com>> wrote:
Is this a bug? I think this is more a question of what is best practice.
Best,
Josh

On Jul 21, 2016, at 10:48 AM, Zhao Xin via swift-users < > swift-users@swift.org<mailto:swift-users@swift.org><mailto: > swift-users@swift.org<mailto:swift-users@swift.org>>> wrote:

Then you should file a bug.

Zhaoxin

On Fri, Jul 22, 2016 at 1:03 AM, Tod Cunningham < > tcunningham@vectorform.com<mailto:tcunningham@vectorform.com><mailto: > tcunningham@vectorform.com<mailto:tcunningham@vectorform.com>>> wrote:
If Test and Test2 are in separate files, swift doesn’t allow you to do the
override as it “can’t see” the definition of the private method in Test.

From: Zhao Xin <owenzx@gmail.com<mailto:owenzx@gmail.com><mailto:
owenzx@gmail.com<mailto:owenzx@gmail.com>>>
Date: Thursday, July 21, 2016 at 11:06 AM
To: Tod Cunningham <tcunningham@vectorform.com<mailto:
tcunningham@vectorform.com><mailto:tcunningham@vectorform.com<mailto:
tcunningham@vectorform.com>>>
Cc: "swift-users@swift.org<mailto:swift-users@swift.org><mailto:
swift-users@swift.org<mailto:swift-users@swift.org>>" <
swift-users@swift.org<mailto:swift-users@swift.org><mailto:
swift-users@swift.org<mailto:swift-users@swift.org>>>
Subject: Re: [swift-users] @objc and private methods

I think @objc makes the function an Objective-C function, so the private
is no longer making the function private in Swift way, but in Objective-C
way. In C++, sub-class can call super-class's private method. What you
have to do is to override the function.

class Test {

    @objc private func somefunc() {

        print( "hello 1" )

    }

}

class Test2: Test {

    @objc override private func somefunc() {

        print( "hello 2" )

    }

}

Zhaoxin

On Thu, Jul 21, 2016 at 10:25 PM, Tod Cunningham via swift-users < > swift-users@swift.org<mailto:swift-users@swift.org><mailto: > swift-users@swift.org<mailto:swift-users@swift.org>><mailto: > swift-users@swift.org<mailto:swift-users@swift.org><mailto: > swift-users@swift.org<mailto:swift-users@swift.org>>>> wrote:
I wanted to get thoughts on the use of @objc and private methods. Should
this usage be avoided or leveraged?

I have seen some code where things like UIButton and Gesture recognizer
handlers are defined as being private. I would have thought this would
result in a compiler error given objective-c doesn’t support private
accessors. However, it compiles and works as expected (kind of).

One plus for defining the handlers as private is they aren’t visible to
swift outside of the file they are defined in. The problem is you can run
into some issues with inheritance if you define the same handler in a
derived class. Take the following simple example:

class Test {
    @objc private func somefunc() {
        print( "hello 1" )
    }
}

-- in another file –

class Test2: Test {
    @objc private func somefunc() {
        print( "hello 2" )
    }
}

This will result in the following compiler error:

Method 'somefunc()' with Objective-C selector 'somefunc' conflicts with
method 'somefunc()' from superclass 'Test' with the same Objective-C
selector

That error makes sense in an Objective-C context as Test2 has two
different methods defined with the same objective-c selector (somefunc).
Swift can tell them apart as they are private to each class, but Obj-C
can’t tell them apart as they have the same selector thus the error.

One workaround would be to give the method a different Objective-C names
such as @objc(test2_somefunc); however, that could really lead to some
unexpected results depending on what selector is used to call somefunc.
Test2 would need to “register” a different selector for somefunc then Test
does for whatever is calling it on the Objective-C side (yuck!).

This can of course be solved by not making the method private which allows
Test2 to explicitly override somefunc.

class Test {
   @objc func somefunc() {
       print( "hello 1" )
   }
}

-- in another file –

class Test2: Test {
   @objc override func somefunc() {
       print( "hello 2" )
   }
}

I would say that when declaring @objc methods they shouldn’t be private
and should have the same (public/internal) access method as their
containing class. What’s your thoughts? Why does swift allow a method to
be declared as both @objc and private?

Thanks,

_______________________________________________
swift-users mailing list
swift-users@swift.org<mailto:swift-users@swift.org><mailto:
swift-users@swift.org<mailto:swift-users@swift.org>><mailto:
swift-users@swift.org<mailto:swift-users@swift.org><mailto:
swift-users@swift.org<mailto:swift-users@swift.org>>>
https://lists.swift.org/mailman/listinfo/swift-users

_______________________________________________
swift-users mailing list
swift-users@swift.org<mailto:swift-users@swift.org><mailto:
swift-users@swift.org<mailto:swift-users@swift.org>>
https://lists.swift.org/mailman/listinfo/swift-users

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users