I have read some posts like this one about the difference between subclassing NSObject in Swift or just having its native base class with no subclassing. But they all are a bit old posts, and I am not clear about this topic.
When should you subclass NSObject? What is the actual difference between subclassing it and not subclassing? What is currently the recommendation in Swift?
Apple's documentation about NSObject states the following as an introduction:
NSObject is the root class of most Objective-C class hierarchies. Through NSObject, objects inherit a basic interface to the runtime system and the ability to behave as Objective-C objects.
As this would suggest, you need to subclass NSObject for types introduced in your code whenever instances of that type need to behave like an Objective-C object (or the class itself, in some rarer cases).
I am not aware of super explicit Apple provided written guidance on when not to subclass NSObject, beyond suggesting reducing dynamic dispatch or presenting code reuse paradigms using that do not relying on subclassing but protocol extensions, i.e. code reuse that is generally more static dispatch and value type friendly). I believe it is fair to say though that most Swift programmers have taken hints from Apple, and Swift language features as signs to avoid introducing NSObject based types when the above-mentioned need is not there. That is, as a general rule, only introduce NSObject based types when you actually need the Objective-C dynamism, most commonly when you need to interface with Cocoa APIs (especially common when your code is UI related: e.g. view controllers, views).
As pointed out in an answer to the question you link to, with Objective-C style dynamism comes the performance of objc_msgSend based method dispatch. Although methods in Swift classes are also virtual, the compiler is able to use faster means of dispatching methods when you don't explicitly mark the methods with the #objc attribute – especially when Whole Module Optimization is toggled on, and even more so in Swift 3 where classes are not by default open for subclassing beyond the module that defines the type.
Beyond avoiding NSObject, you can also avoid class based reference types altogether in many cases when writing Swift. Take a look at for instance the value type WWDC videos linked above, or for example this blog post as an introduction. Briefly, using value types you gain good local reasoning, often avoid dynamic memory allocation and reference counting overhead (though not universally so – structs with reference types as fields being the caveat).
One reason to subclass NSObject is if you need to save some data. NSObject and all it entails remains (AFAIK) the simplest way to get to NSCoding which you need to write to a file.
some insights can be found here or here
Another case when you must subclass NSObject is when you want your subclass to be an observer for KVO, i.e.
addObserver(_ observer: NSObject, forKeyPath keyPath: String, options: NSKeyValueObservingOptions = [], context: UnsafeMutableRawPointer?)
requires the observer to be an NSObject (or an array or set).
Related
In regards to UITableView & UICollectionView & their respective protocols, UITableViewDataSource & UITableViewDelegate + UICollectionViewDelegate & UICollectionViewDataSource -- are there any pros and cons to implementing one method, but not the other or a particular set of methods and not the rest of the methods or a unique combination of specific methods?
For example, if I am to implement heightForFooter but not viewForFooter - what happens or can happen? Does this negative impact performance or the scroll of the table view?
Is there a guide which shows that which if any methods are implemented, others should be combined and dually implemented alongside them?
Re: correctness
Is there a guide which shows that which if any methods are implemented, others should be combined and dually implemented alongside them?
Not from what I've seen, though sometimes the documentation mentions it. E.g. from the docs of NSTableViewDataSource:
If you’re not using Cocoa bindings to provide data to the table view, the following methods are required:
numberOfRows(in:)
tableView(_:objectValueFor:row:)
tableView(_:setObjectValue:for:row:) (cell-based tables only)
In general, if a method is optional, but required from the context, then there will be a runtime error telling you to implment it, e.g.:
Illegal NSTableView data source (Foo). Must implement numberOfRowsInTableView: and tableView:objectValueForTableColumn:row:
Either that, or stuff will silently fail (e.g. if you don't implement NSTableViewDelegate.tableView(_:viewFor:row:), no drawing will happen, and all your cells will just be blank views.
Re: performance
There shouldn't be any real performance difference with not implementing optional methods.
Each of these methods is likely called as if you had this in Swift (most of these frameworks are still implemented in Objective C):
let result: Result? = yourTarget.someMethod?(someArg)
which is really just shorthand for:
let result: Result? = yourTarget.responds(to: #selector(YourTargetsClass.someMethod))
? target.method(someArg)
: nil
That is, it's one dynamic method lookup to check if your object responds to the message, and one dynamic message send to actually invoke the method (for the case where it does respond).
There's a teeny tiny optimization that one could squeeze out here: if your method implementation is empty, then you're better off not having it at all. That will prevent a needless message send. Though it's obviously not something to worry about until you're sure it's a hotspot in a profiler.
Of course, nothing stops a library author from writing:
if yourObject.responds(to: #selector(someMessage)) {
doSomethingVeryExpensiveForNoGoodReason()
}
... but that's unlikely.
It's not possible to subclass DispatchGroup, how to do so?
Note:
this has finally been fixed in iOS 10+
Example, carry a stateful package with a group,
class PushDispatchGroup: DispatchGroup {
var sentIds: [(tableName: String, rowId: String)] = []
}
thanks to shallowThought for pointing out this is fixed in iOS10.
how to inherit from a class which is 'only visible via the Objective-C runtime'?
You don't.
This is not wrapped around a proper "object" the way you're thinking about it. It's wrapped around a dispatch_group, which is a C struct. This class is not designed to be subclassed and does not bridge in a normal way to ObjC, so you can't subclass it there either.
"Objects" that bridge directly to low level C types often have very unusual structures that parts of the system are hard-coded to know how to deal with (this happens all the time with toll-free bridging like NSString and CFString). In many cases, the types are designed to be identical in memory layout through careful choice of structure (I haven't picked apart DispatchGroup, but it looks like one from this group). When that's true, you can't add any storage because then the memory layout will be different and you break the bridging.
As various commenters have said, you also shouldn't be doing this, which is why there is no easy answer for how to do this. Classes that are not explicitly designed for subclassing are intentionally difficult or impossible to subclass in Swift (this comes up regularly around less tricky types than DispatchGroup, and the answer is the same: it's intentional; don't do it).
Specifically, how does Swift memory management work with optionals using the delegate pattern?
Being accustomed to writing the delegate pattern in Objective-C, my instinct is to make the delegate weak. For example, in Objective-C:
#property (weak) id<FooDelegate> delegate;
However, doing this in Swift isn't so straight-forward.
If we have just a normal looking protocol:
protocol FooDelegate {
func doStuff()
}
We cannot declare variables of this type as weak:
weak var delegate: FooDelegate?
Produces the error:
'weak' cannot be applied to non-class type 'FooDelegate'
So we either don't use the keyword weak, which allows us to use structs and enums as delegates, or we change our protocol to the following:
protocol FooDelegate: class {
func doStuff()
}
Which allows us to use weak, but does not allow us to use structs or enums.
If I don't make my protocol a class protocol, and therefore do not use weak for my variable, I'm creating a retain cycle, correct?
Is there any imaginable reason why any protocol intended to be used as a delegate protocol shouldn't be a class protocol so that variables of this type can be weak?
I primarily ask, because in the delegation section of the Apple official documentation on Swift protocols, they provide an example of a non-class protocol and a non-weak variable used as the delegate to their class:
protocol DiceGameDelegate {
func gameDidStart(game: DiceGame)
func game(game: DiceGame, didStartNewTurnWithDiceRoll diceRoll: Int)
func gameDidEnd(game: DiceGame)
}
class SnakesAndLadders: DiceGame {
let finalSquare = 25
let dice = Dice(sides: 6, generator: LinearCongruentialGenerator())
var square = 0
var board: [Int]
init() {
board = [Int](count: finalSquare + 1, repeatedValue: 0)
board[03] = +08; board[06] = +11; board[09] = +09; board[10] = +02
board[14] = -10; board[19] = -11; board[22] = -02; board[24] = -08
}
var delegate: DiceGameDelegate?
func play() {
square = 0
delegate?.gameDidStart(self)
gameLoop: while square != finalSquare {
let diceRoll = dice.roll()
delegate?.game(self, didStartNewTurnWithDiceRoll: diceRoll)
switch square + diceRoll {
case finalSquare:
break gameLoop
case let newSquare where newSquare > finalSquare:
continue gameLoop
default:
square += diceRoll
square += board[square]
}
}
delegate?.gameDidEnd(self)
}
}
Should we take this as a hint that Apple thinks we should be using structs as delegates? Or is this simply a bad example, and realistically, delegate protocols should be declared as class-only protocols so that the delegated object can hold a weak reference to its delegate?
Should we take this as a hint that Apple thinks we should be using structs as delegates? Or is this simply a bad example, and realistically, delegate protocols should be declared as class-only protocols so that the delegated object can hold a weak reference to its delegate?
Here's the thing. In real life Cocoa programming, the delegate is likely to be an existing class. It is a class because it exists for some other purpose that only a class can satisfy - because Cocoa demands it.
For example, very often, to take iOS as an example, one view controller needs to act as another view controller's delegate for purposes of arranging a message back and forth between them. Ownership of the view controllers is dictated by the view controller hierarchy and by nothing else. So, in Swift, just as in Objective-C, you had better make that delegate property weak, because it would be terrible if one view controller suddenly took memory management ownership of another view controller!
So, in the real world of the Cocoa framework, there is serious danger of incorrect ownership or of a retain cycle. And that is the problem that weak solves. But it only works, as you rightly say, with classes.
The example in the book, however, is about some objects living off in an abstract made-up artificial Swift-only world. In that world, as long as you aren't in danger of circularity (retain cycle), there's no reason not to use structs and there's no reason to worry about memory management. But that world is not the world you will usually be programming in! And that world is not the framework Cocoa world that your Objective-C delegate pattern comes from and belongs to.
Yes, this example is a bit of an oddity.
Because the example uses a non-class protocol type, it has to expect a possible struct implementing the protocol, which means that the DiceGame instance owns its delegate. And indeed, that violates typical assumptions about the delegate pattern.
It doesn't lead to a reference cycle in this case because the DiceGameTracker is a fictional object that doesn't own the DiceGame itself — but in a real-world app it's possible, even likely, that a delegate might also be the owner of the delegating object. (For example, a view controller might own the DiceGame, and implement DiceGameDelegate so it can update its UI in response to game events.)
That kind of reference cycle would probably turn into a confusing mess if either the game, its delegate, or the type implementing one or both of those protocols were a value type — because value types are copied, some of the variables in your setup would end up being distinct copies of the game (or game's owner).
Realistically one would expect to use reference types (classes) to implement this anyway, even if the protocol declaration leaves open the possibility of doing it otherwise. Even in a hypothetical Swift-only world, it probably makes sense to do it that way... generally whenever you have something with long life, internal mutable state, and a usage pattern that has it being accessed by potentially multiple other actors, you want a class type, even if you can sort of fake otherwise with value types and var.
If you must have structs and emums in your protocol, then if you make your delegate nil just before you close the view controller, then this breaks the retain cycle. I verified this in Allocations in Instruments.
// view controller about to close
objectCreatedByMe.delegate = nil
It's an optional, so this is valid.
Suppose I have this:
#interface ThingManager : NSObject
#property Thing *aThing;
#end
Is there a way for aThing to know at runtime that it is a property of ThingManager?
You start with the question:
Is there a way for aThing to know at runtime that it is a property of ThingManager?
Though not completely clear the answers so far have assumed you want aThing to be able to determine whether an instance of ThingManger is managing it.
So at this point we know that the ThingManger class knows about the Thing class, and you now appear to want the reverse - you ask can a Thing find its ThingManager?
However when someone answers that you comment
So Thing and ThingManager need to know about each other? Mmmm... Bad for loose coupling.
Hmmm... How can a Thing ask what its ThingManager is if you don't want it to know about ThingManagers?
Is everybody's interpretation of your question wrong?
Maybe you are concerned not about loose coupling but about strong reference cycles? If the two know about each other, and create a strong cycle in doing so, then there is a risk they will keep each other alive long after the need for either by your application - is that the concern?
But that is addressed by #DrummerB - you use a weak property on Thing which references its managing ThingManager. So it would appear that strong reference cycles are not your concern either...
Then you comment:
Isn't there a way to see who's referencing an object at runtime?
As stated generally that is a very different question. The short answer to this is no[*].
Are you asking whether it is possible to write a method which a Thing can call to find the ThingManager that is managing it without any references being maintained between Thing instances and ThingManager instances?
If so here is an outline algorithm:
Have the ThingManager class keep a collection of all create and alive instances of itself. The alive requirement requires this collection be some kind of weak collection (design your own or do a search for weak collections).
Add a class method to ThingManager which finds the manager for a Thing, e.g. something like + (ThingManager *) managerFor:(Thing *)thing.
Have your Thing instances call [ThingManager managerFor:self] when they need to know their manager.
That of course doesn't address your concern over loose coupling - the two classes must still know of each others existence...
Which brings you back to the direct solution of having Thing have a manager property. If you want to reduce the coupling you can type this property as id, so its any old object, or id<SomeMinimalManagerProtocol> so its any old object provide it implements some minimal set of management methods you've define in the protocol SomeMinimalManagerProtocol.
Take a look at NSWindow and NSWindowController - they know about each other.
HTH
[*] The long answer is that (Objective-)C(++) are not designed to ensure all references can be found. This is why you hear phrases such as "conservative garbage collection". There was a garbage collector for just Objective-C objects, which was supported by internal changes to the runtime, but that is now deprecated and its machinery wasn't easily accessible to applications to apply to other uses.
Not unless you tell it, that it is.
You could add a ThingManager weak property to Thing and implement the setter in ThingManager like this:
- (void)setAThing:(Thing *)thing {
if (_aThing != thing) {
_aThing = thing;
_aThing.manager = self; // this is the relevant line
}
}
Not unless you have a custom setter for your aThing property that sets something on the Thing object to tell it that it is. You could have the aThing setter method set a property that you add to Thing that tells it who its manager is.
what is the exact meaning of delegate in iphone?how it is implemented in UIViewController?
A delegate is an object that usually reacts to some event in another object and/or can affect how another object behaves. The objects work together for the greater good of completing a task. Typically a delegate object will be shared by many other objects that have a more specific task to carry out. The delegate itself will be more abstract and should be very reusable for different tasks. The object which contains the delegate typically sends the delegate a message when a triggered event occurs, giving the delegate an opportunity to carry out its specified task.
There's more documentation here that you should read to understand the delegate pattern in Cocoa and Cocoa touch, particularly with how delegation is used between UIWindow and UIView. It is an integral design pattern in iPhone architecture and one that should be mastered if you wish to design a clean application.
Delegates are used to delegate tasks of objects to their owner (or any object, really). A good reason for this is it makes it easier to use composition instead of inheritance. Delegates are a reference to an object that conform to a specified protocol so you can guarantee it will implement the required methods. A good example is UIApplicationDelegate. Notice how the delegated methods (from the protocol) use verbs that applicationDid, applicationShould, applicationWill etc. Usually delegate methods either ask for permission to do something (and choose to do it this way, in a method, rather than with just a BOOL property, for more flexibility) or notify the delegate of an event that will happen or did happen.
Delegation is a pattern and the term means the same in Cocoa.
A delegate is not implemented in a UIViewController. Different kinds of view controllers are assigned a delegate to handle certain tasks. One of the best examples (if we're talking iPhone) is the UITableViewDelegate, which is called to do certain things when certain table-related events occur.
A delegate is used to communicate/pass data b/w two objects of a class/struct to complete a task.
For example: Consider firstVC(sender or Delegator or CEO) which sends confidential data to secondVC(receiver or Delegate or Secretary).
This is done by making secondVC conforming to a
protocol passDataDelegate { func passdata(data: String) }
class secondVC : UIViewController, passDataDelegate {
func passdata(data: String) {
print("CEO passed //(data)")
}
}
class firstVC : UIViewController {
var delegate : passDataDelegate?
}
Now create objects of both firstVC & secondVC
let sender = firstVC()
let receiver = secondVC()
Since, receiver conforms to protocol passDataDelegate. So, it is having type either as UIViewController or passDataDelegate because if a class conforms to a protocol then the object of its class can have protocol as type.
Hence, assign sender.delegate = receiver
Now, we can CEO(sender) can pass data to Secretary(receiver) through its delegate property as
sender.delegate?.passdata("Confidential data")
Output: CEO passed Confidential data
Now the Secretary(receiver) can use that data to complete her further task.
The concept of delegation is very common in iOS. An object will often rely on another object to help it out with certain tasks. This separation of concerns keeps the system simple as each object does only what it is good at and lets other objects take care of the rest. The table view offers a great example of this.