Getter for object property needs to return UnsafeMutablePointer<T>? - ios

I'm working in Swift and one of the protocols I'm using needs to return an UnsafeMutablePointer<T> of a particular object.
I have something like this:
#objc var myProperty:UnsafeMutablePointer<someObject>
{
get
{
// I call a class function here to get a 'someObject'
// return object which I need to pass back a pointer to it.
return UnsafeMutablePointer<someObject>
}
}
The problem is that Xcode doesn't like this. It complains that '>' is not a unary operator.
I've also tried removing the UnsafeMutablePointer<> and use an & in front of someObject but it complains that the & is to be used immediately in a list of arguments for a function.
I suppose I just can't find the right syntax for this? Any help would be appreciated.

If someObject has the type SomeClass, then you need to update your declaration like this:
#objc var myProperty:UnsafeMutablePointer<SomeClass>
{
get
{
return UnsafeMutablePointer<SomeClass>(unsafeAddressOf(someObject))
}
}
The generic argument needs to be the type of the returned data, and you also need to intialize a specialized UnsafeMutablePointer with the memory address of the desired object.

Related

This is one thing I do not understand in Swift

Consider these lines:
I create a NSButton based class with this:
typealias onClickHandler = (NSTextfieldSuper)->Void
var onClick: onClickHandler?
When the user clicks on an instance of that button, I do this:
if (self.onClick != nil) {
onClick?(self)
}
I use that button later, from another class, with this:
let button = SuperButton()
button.onClick = { (textField: NSTextfieldSuper)->Void in
}
I am not sure if this is the correct syntax. I would like to process the button sent from the first closure on the parent class, where the button is created.
This was the only form I was able to type this without Xcode complaining. If this is correct, what is the purpose of this ->Void there? What could this possibly returning?
I just want to process that button sent.
By the way, as a bonus, I have to initialize several buttons with this, all running the same function. It would be nice to do something like
func doSomething () {
}
and then
let button = SuperButton()
button.onClick = doSomething
any ideas?
This was the only form I was able to type this without Xcode complaining. If this is correct, what is the purpose of this ->Void there? What could this possibly returning?
It is the same as in your typealias, in Swift a function type has the form:
(parameter definitions) -> return type
and functions which return nothing have a return type of Void (similar to C). The full form off a closure expression is:
{ (parameter definitions) ->return typeinbody}
Without any inference this expression provides the full type of the closure, and the -> Void Return type in your example specifies that your closure returns nothing. In your assignment this full type will be checked at compile time to conform to the type of onClick.
Now Swift will infer lots of stuff and there are various shorthands available for closure expressions, you will find that Swift accepts:
button.onClick = { textField in }
as well here with both the argument and return types of the closure being inferred.
By the way, as a bonus, [...] any ideas?
Just make the types match:
func doSomething(textField : NSTextfieldSuper) { }
button.onClick = doSomething
Unlike in (Objective-)C functions and closures (blocks in C) are interchangeable (as they are in plenty of other languages, C is the oddfellow here)
HTH

Swift generic class, inheritance and covariance

I'm faced with the problem of using generic class and inheritance.
Brief description of the problem:
I have a base class called BookPageDataSource and two inherited classes (ReadingBookPageDataSource and StarsBookPageDataSource) with different implementations.
Also, I have a generic class BookPageViewController that contains the generic parameter of this data source and two inherited classes (ReadingBookPageViewController and StarsBookPageViewController) from this class.
I need to write a method the return parameter of which is BookPageViewController<DataSource>.
// Data Sources
class BookPageDataSource { }
class ReadingBookPageDataSource: BookPageDataSource { }
class StarsBookPageDataSource: BookPageDataSource { }
// Controllers
class BookPageViewController<DataSource: BookPageDataSource>: UIViewController {
let dataSource: DataSource
init(dataSource: DataSource) {
self.dataSource = dataSource
super.init(nibName: nil, bundle: nil)
}
required init?(coder aDecoder: NSCoder) {
return nil
}
}
final class ReadingBookPageViewController: BookPageViewController<ReadingBookPageDataSource> { }
final class StarsBookPageViewController: BookPageViewController<StarsBookPageDataSource> { }
// Communication
class Pager {
func currentPageController<DataSource>(at index: Int) -> BookPageViewController<DataSource> {
// for example
if index == 0 {
// How to remove the cast from the line below?
return readingPageController() as! BookPageViewController<DataSource>
}
return starsPageController() as! BookPageViewController<DataSource>
}
private func readingPageController() -> ReadingBookPageViewController {
return ReadingBookPageViewController(dataSource: ReadingBookPageDataSource())
}
private func starsPageController() -> StarsBookPageViewController {
return StarsBookPageViewController(dataSource: StarsBookPageDataSource())
}
}
The method currentPageController always crashes, because the DataSource is always equals to BookPageDataSource, not to ReadingBookPageDataSource or StarsBookPageDataSource.
Conceptual Discussion
Your concept for the architecture is flawed and this is leading to your issue.
Simple Generics Example
Here's a very simple example of a generic function, which just returns the value you give it:
func echo <T> (_ value: T) -> T { return value }
Because this function is generic, there is ambiguity about the type that it uses. What is T? Swift is a type-safe language, which means that ultimately there is not allowed to be any ambiguity about type whatsoever. So why is this echo function allowed? The answer is that when I actually use this function somewhere, the ambiguity about the type will be removed. For example:
let myValue = echo(7) // myValue is now of type Int and has the value 7
In the act of using this generic function I have removed the ambiguity by passing it an Int, and therefore the compiler has no uncertainty about the types involved.
Your Function
func currentPageController <DataSource> (at index: Int) -> BookPageViewController<DataSource>
Your function only uses the generic parameter DataSource in the return type, not in the input - how is the compiler supposed figure out what DataSource is?* I assume this is how you imagined using your function:
let pager = Pager()
let controller = pager.currentPageController(at: 0)
But now, what is the type of controller? What can you expect to be able to do with it? It seems that you're hoping that controller will take on the correct type based on the value that you pass in (0), but this is not how it works. The generic parameter is determined based on the type of the input, not the value of the input. You're hoping that passing in 0 will yield one return type, while 1 will yield a different one - but this is forbidden in Swift. Both 0 and 1 are of type Int, and the type is all that can matter.
As is usually the case with Swift, it is not the language/compiler that is preventing you from doing something. It is that you haven't yet logically formulated what is even is that you want, and the compiler is just informing you of the fact that what you've written so far doesn't make sense.
Solutions
Let's move on to giving you a solution though.
UIViewController Functionality
Presumably there is something that you wanted to use controller for. What is it that you actually need? If you just want to push it onto a navigation controller then you don't need it to be a BookPageViewController. You only need it to be a UIViewController to use that functionality, so your function can become this:
func currentPageController (at index: Int) -> UIViewController {
if index == 0 {
return readingPageController()
}
return starsPageController()
}
And you can push the controller that it returns onto a navigation stack.
Custom Functionality (Non-Generic)
If, however, you need to use some functionality which is specific to a BookPageViewController then it depends what it is you want to do. If there is a method on BookPageViewController like this:
func doSomething (input: Int) -> String
which doesn't make use of the generic parameter DataSource then probably you'll want to separate out that function into its own protocol/superclass which isn't generic. For example:
protocol DoesSomething {
func doSomething (input: Int) -> String
}
and then have BookPageViewController conform to it:
extension BookPageViewController: DoesSomething {
func doSomething (input: Int) -> String {
return "put your implementation here"
}
}
Now the return type of your function can be this non-generic protocol:
func currentPageController (at index: Int) -> DoesSomething {
if index == 0 {
return readingPageController()
}
return starsPageController()
}
and you can use it like this:
let pager = Pager()
let controller = pager.currentPageController(at: 0)
let retrievedValue = controller.doSomething(input: 7)
Of course, if the return type is no longer a UIViewController of any sort then you probably want to consider renaming the function and the related variables.
Custom Functionality (Generic)
The other option is that you can't separate out the functionality you need into a non-generic protocol/superclass because this functionality makes use of the generic parameter DataSource. A basic example is:
extension BookPageViewController {
func setDataSource (_ newValue: DataSource) {
self.dataSource = newValue
}
}
So in this case you really do need the return type of your function to be BookPageViewController<DataSource>. What do you do? Well, if what you really want is to use the setDataSource(_:) method defined above then you must have a DataSource object that you plan to pass in as an argument, right? If this is the case then we're making progress. Previously, you only had some Int value which you were passing into your function and the problem was that you couldn't specify your generic return type with that. But if you already have a BookPageDataSource value then it is at least logically possible for you to use this to specialize your
function.
What you say you want, however, is to just use an Int to get the controller at that index, regardless of what the DataSource type is. But if you don't care what the DataSource is of the returned BookPageViewController then how can you expect to set its DataSource to something else using the setDataSource(_:) method?
You see, the problem solves itself. The only reason you would need the return type of your function to be generic is if the subsequent functionality you need to make use of uses that generic type, but if this is the case then the controller you get back can't have just any old DataSource (you just wanted whichever one corresponds to the index you provide) - you need it to have exactly the type of DataSource which you plan to pass in when you use it, otherwise you're giving it the wrong type.
So the ultimate answer to your question is that, in the way that you were conceiving of it, there is no possible use for the function you were trying to construct. What's very cool about the way Swift is architected is that the compiler is actually able to figure out that logical flaw and prevent you from building your code until you've re-conceptualized it.
Footnote:
* It is possible to have a generic function which only uses the generic parameter in the return type and not in the input, but this won't help you here.

Type Method in swift?

I am trying a bit of type (aka class) method but am confused on the real world application of such methods. e.g. In the following code from tutorialspoint.com -
class Math
{
class func abs(number: Int) -> Int
{
if number < 0
{
return (-number)
}
else
{
return number
}
}
}
let no = Math.abs(-35)
println(no)
So my question is that what is happening here when I am writing a type method. At what point of my programming may I need this. Can any one explain with a bit clear and simple example.
these kinds of functions are useful when you dont actually need an instance of the type to be made to be able to call it, eg helper methods. take the example you posted, if you call the abs function, you dont really need to make a Math object instantiated to do that (you could be seems unnecessary).
if your abs function wasnt a type method, you would have to go like this
var mathObject = Math()
mathObject.abs(-35)
as apposed to the way you have it in you example
Math.abs(-35)
both statements achieve the same goal, but the 2nd is more elegant (and memory efficient).
there are other reasons as well for using type methods, but this is just the simplest example of one (look up what a singleton is, for another example)
class C {
class func foo(){}
// Type method is always static !!!
static func boo() {}
}
class D: C {
override class func foo() {}
// this is not possible for 'Type method'
override static func boo() {} // error !!!!
}

Cannot have a function with same name as parameter type

I have a class that conforms to an Objective-C protocol and has a function with the same name as one of it's parameter types.
class MessageDataController: NSObject, MCOHTMLRendererDelegate {
#objc func MCOAbstractMessage(msg: MCOAbstractMessage!, canPreviewPart part: MCOAbstractPart!) -> Bool {
return false
}
}
This causes Xcode to give the error
"Use of undeclared type 'MCOAbstractMessage'"
for using MCOAbstractMessage as both the function name and a parameter type. It doesn't give an error if I change the function name to abstractMessage or similar. I think the issue is related to this question and/or this issue but am unsure how to resolve. My project's header file is correctly configured to use MailCore2.
Tried changing the declaration to:
#objc(MCOAbstractMessage:canPreviewPart:) func abstractMessage(msg: MCOAbstractMessage!, canPreviewPart part: MCOAbstractPart!) -> Bool
which gives the error
"~/src/project/MessageDataController.swift:11:52: Objective-C method 'MCOAbstractMessage:canPreviewPart:' provided by method 'abstractMessage(:canPreviewPart:)' conflicts with optional requirement method 'MCOAbstractMessage(:canPreviewPart:)' in protocol 'MCOHTMLRendererDelegate'"
This may be solved by using the fully-qualified type name in the parameter list. I'm not familiar with the library you are using, but the suggestion below assumes that the type MCOAbstractMessage is declared in a module called MCO. Prepend MCO. to the type name.
class MessageDataController: NSObject, MCOHTMLRendererDelegate {
#objc func MCOAbstractMessage(msg: MCO.MCOAbstractMessage!, canPreviewPart part: MCOAbstractPart!) -> Bool {
return false
}
}
I tested this by adding a method called Array to one of my classes. Sure enough it threw compiler errors everywhere else that I had used Array as a type. I prefixed all of those as Swift.Array and all was well.
If you want a shorter version, use a typealias,

Filter array in a category/extension

For convenience, in a little experiment I am doing, I would like to extend Array to provide some app specific functionalities. This specific extension is not necessary best practice, but I am just curious about solving the Swift issues I am having.
Given a custom class Section, my extension (with partially extended closure) is:
extension Array {
func onlyFullSection() -> Array<Section> {
return self.filter {
(a:Section) -> Bool in
return a.isFullSection()
}
}
}
The error I get is: "T" is not a subtype of "Section".
I tried to fix it with all the sauces (changing types, casting, etc...) but still get similar errors.
This other variant:
extension Array {
func onlyFullSection() -> Array<Section> {
return (self as Array<Section>).filter {
(a:Section) -> Bool in
return a.isFullSection()
} as Array<Section>
}
throws: Cannot convert the expression's type 'Array<Section>' to type 'Array<Section>'
Any clue on what I am doing wrong? Thanks!
It is because you are extending T[] and not Section[]. That means that Int[] will also have your additional method. That might not be the best idea (since it will crash badly).
Swift currently does not allow you to extend a specialised generic type like Section[].
But if you really, really want to do it, here is one way to force a cast, use reinterpretCast, which Apple describes as follows
/// A brutal bit-cast of something to anything of the same size
func reinterpretCast<T, U>(x: T) -> U
You can use it like this:
extension Array {
func onlyFullSection() -> Section[] {
let sections : Section[] = reinterpretCast(self)
return sections.filter{ $0.isFullSection() }
}
}
But please don't.
The problem is that since the Array class is actually a generic Array<T>, you are extending Array<T>. And apparently you can't cast between generic types (i.e. <T> to <Section>), so I believe you'll have to make a new array and just push the appropriate objects into it.
17> extension Array {
18. func onlyFullSection() -> Array<Section> {
19. var ary = Array<Section>()
20. for s in self {
21. if (s as Section).isFullSection() {
22. ary.append(s as Section)
23. }
24. }
25. return ary
26. }
27. }
You could also create a helper method to convert between generic types for you, but in this instance that would just create an unnecessary temporary object.
Remember that the language is still heavily in flux so it's possible this will change. I think it's unlikely that we'll get the ability to cast between generic types, but I hope we'll at least be able to extend particular generics.

Resources