Skip to content

Commit

Permalink
Fix issues with standard updater controller initialization (#1958)
Browse files Browse the repository at this point in the history
* Fix init'ing updater delegates in standard updater controller in nibs

* Convert updaterDelegate/userDriverDelegate properties to ivars

This should allow connecting outlets in IB while disallowing setting them programmatically.
  • Loading branch information
zorgiepoo authored Sep 19, 2021
1 parent 1dea970 commit eba1734
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 36 deletions.
25 changes: 11 additions & 14 deletions Sparkle/SPUStandardUpdaterController.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,20 +37,17 @@ NS_ASSUME_NONNULL_BEGIN
If you need more control over what bundle you want to update, or you want to provide a custom user interface (via `SPUUserDriver`), please use `SPUUpdater` directly instead.
*/
SU_EXPORT @interface SPUStandardUpdaterController : NSObject

/**
Interface builder outlet for the updater's delegate.
This property should only be set using Interface Builder by creating a connection using the outlet.
*/
@property (nonatomic, weak, nullable) IBOutlet id<SPUUpdaterDelegate> updaterDelegate;

/**
Interface builder outlet for the user driver's delegate.
This property should only be set using Interface Builder by creating a connection using the outlet.
*/
@property (nonatomic, weak, nullable) IBOutlet id<SPUStandardUserDriverDelegate> userDriverDelegate;
{
/**
* Interface builder outlet for the updater's delegate.
*/
IBOutlet __weak id<SPUUpdaterDelegate> updaterDelegate;

/**
* Interface builder outlet for the user driver's delegate.
*/
IBOutlet __weak id<SPUStandardUserDriverDelegate> userDriverDelegate;
}

/**
Accessible property for the updater. Some properties on the updater can be binded via KVO
Expand Down
52 changes: 30 additions & 22 deletions Sparkle/SPUStandardUpdaterController.m
Original file line number Diff line number Diff line change
Expand Up @@ -17,49 +17,57 @@
#import "SULocalizations.h"
#import <AppKit/AppKit.h>

// We use public instance variables instead of properties for the updater / user driver delegates
// because we want them to be connectable outlets from Interface Builder, but we do not want their setters to be invoked
// programmatically.

@interface SPUStandardUpdaterController () <NSMenuItemValidation>

@property (nonatomic) SPUUpdater *updater;
@property (nonatomic) id<SPUUserDriver> userDriver;

@end

@implementation SPUStandardUpdaterController

@synthesize updater = _updater;
@synthesize userDriver = _userDriver;
@synthesize updaterDelegate = _updaterDelegate;
@synthesize userDriverDelegate = _userDriverDelegate;

- (instancetype)init
{
// Updater will be later started in -awakeFromNib
// Our updater delegate and user driver delegate outlets will be connected by then too.
// For now we can make sure the updater/userDriver are accessible
return [self initWithStartingUpdater:NO updaterDelegate:nil userDriverDelegate:nil];
}

- (void)awakeFromNib
{
// Note: awakeFromNib might be called more than once but -startUpdate handles that
// Note: awakeFromNib might be called more than once
// We have to use awakeFromNib otherwise the delegate outlets may not be connected yet,
// and we aren't a proper window or view controller, so we don't have a proper "did load" point
[self startUpdater];
if (self.updater == nil) {
[self _initUpdater];
[self startUpdater];
}
}

- (instancetype)initWithUpdaterDelegate:(nullable id<SPUUpdaterDelegate>)updaterDelegate userDriverDelegate:(nullable id<SPUStandardUserDriverDelegate>)userDriverDelegate
- (void)_initUpdater
{
return [self initWithStartingUpdater:YES updaterDelegate:updaterDelegate userDriverDelegate:userDriverDelegate];
NSBundle *hostBundle = [NSBundle mainBundle];
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdirect-ivar-access"
SPUStandardUserDriver *userDriver = [[SPUStandardUserDriver alloc] initWithHostBundle:hostBundle delegate:self->userDriverDelegate];

self.updater = [[SPUUpdater alloc] initWithHostBundle:hostBundle applicationBundle:hostBundle userDriver:userDriver delegate:self->updaterDelegate];
self.userDriver = userDriver;
#pragma clang diagnostic pop
}

- (instancetype)initWithStartingUpdater:(BOOL)startUpdater updaterDelegate:(nullable id<SPUUpdaterDelegate>)updaterDelegate userDriverDelegate:(nullable id<SPUStandardUserDriverDelegate>)userDriverDelegate
- (instancetype)initWithUpdaterDelegate:(nullable id<SPUUpdaterDelegate>)theUpdaterDelegate userDriverDelegate:(nullable id<SPUStandardUserDriverDelegate>)theUserDriverDelegate
{
return [self initWithStartingUpdater:YES updaterDelegate:theUpdaterDelegate userDriverDelegate:theUserDriverDelegate];
}

- (instancetype)initWithStartingUpdater:(BOOL)startUpdater updaterDelegate:(nullable id<SPUUpdaterDelegate>)theUpdaterDelegate userDriverDelegate:(nullable id<SPUStandardUserDriverDelegate>)theUserDriverDelegate
{
if ((self = [super init])) {
_updaterDelegate = updaterDelegate;
_userDriverDelegate = userDriverDelegate;
self->updaterDelegate = theUpdaterDelegate;
self->userDriverDelegate = theUserDriverDelegate;

NSBundle *hostBundle = [NSBundle mainBundle];
SPUStandardUserDriver *userDriver = [[SPUStandardUserDriver alloc] initWithHostBundle:hostBundle delegate:userDriverDelegate];

_updater = [[SPUUpdater alloc] initWithHostBundle:hostBundle applicationBundle:hostBundle userDriver:userDriver delegate:updaterDelegate];
_userDriver = userDriver;
[self _initUpdater];

if (startUpdater) {
[self startUpdater];
Expand Down

0 comments on commit eba1734

Please sign in to comment.