How to mock UIApplication in Swift? - swift

I'm currently using Quick + Nimble for my unit testing in Swift. I'm building an Inviter class that sends app invites via different methods.
I need to mock out UIApplication to verify that my code calls openURL.
My code so far:
import Quick
import Nimble
import OCMock
extension Inviter {
convenience init(usingMockApplication mockApplication: UIApplication) {
self.init()
application = mockApplication
}
}
class MockUIApplication : UIApplication {
var application = UIApplication.sharedApplication()
var openedURL: String?
override func openURL(url: NSURL) -> Bool {
openedURL = url.absoluteString
return true
}
}
class InviterSpec: QuickSpec {
override func spec() {
describe("Inviter") {
var mockApplication = MockUIApplication()
var inviter = Inviter(usingMockApplication: mockApplication)
beforeEach() {
inviter = Inviter(usingMockApplication: mockApplication)
}
context("for WhatsApp invites") {
beforeEach() {
inviter.inviteViaWhatsAppWithMessage("Invite Message.")
}
it("should tell the application to open WhatsApp") {
expect(mockApplication.openedURL).toNot(beNil())
}
it("should send WhatsApp the right message") {
let message = mockApplication.openedURL?.lastPathComponent
expect(message).to(equal("Invite%Message."))
}
}
}
}
}
In this approach, my app errors at runtime stating there can understandably be only one UIApplication. Previously, one could make MockUIApplication inherit from NSObject, and pass that in. Unfortunately Swift's strict type checking seems to prevent that too.
Would love any ideas.

You are close. Use a protocol for the functions you need.
protocol UIApplicationProtocol {
func openURL(url: NSURL) -> Bool
}
extension UIApplication: UIApplicationProtocol {}
Then you just need to use the protocol instead of the class
extension Inviter {
convenience init(usingMockApplication mockApplication: UIApplicationProtocol) {
self.init()
application = mockApplication
}
}
You will need to modify the Inviter class to use UIApplicationProtocol as well.

Related

How to handle multi-inheritance in Swift?

This is probably 2 swift questions in one...
How do I solve a situation where I want to extend an existing base class (UIView in my case) with functionality that requires stored properties? ...so that I can reuse the code for other classes?
I have tried to solve it through composition below, but I don't know if there is a more obvious way that I just can't see as I am fairly new to swift...
The second question:
In my implementation I have an abstract class ManagedComponentImpl which needs an eventReceiver object which is going to be the containing UIView subclass.
The problem I have with my implementation is that swift forces me to define an object binding where Receiver:NSObject for ManagedComponentImpl, so that I can declare the optional variable eventReceiver as weak. (and I guess I would create a memory leak otherwise). However I would want to use this implementation on a variety of objects (which could of course all inherit NSObject, but they do not actually need to for other reasons but this, so it seems odd). So question number 2: Is there a way to avoid this?
EDIT: And yes! I made a mistake mixing model and view code here, but I guess the fundamental problem remains when you switch UIViewController for UIView :-)
public protocol ManagedConnection {
var connectionKey:String { get set }
}
public protocol ManagedComponent: ConnectionObserver {
var connectionKey:String { get set }
func connectTo()
func disconnectFrom()
}
public protocol EventReceiver: ConnectionObserver {
var variableSet:Set<VariableID>? { get }
var handleVariableUpdates: ((Set<VariableID>)->Void)? { get }
}
class ManagedComponentImpl<Receiver: EventReceiver> where Receiver:NSObject {
public var _connectionKey: String = Shared
//The connection Key
public var connectionKey: String
{
set {
disconnectFrom()
self._connectionKey = newValue
connectTo()
}
get {
return _connectionKey
}
}
// The varset needed by this control
weak var eventReceiver:Receiver!
// handler for the status pane variables
//
var connectionObserverHandlerID:UInt16 = 0
var eventHandlerID:UInt16 = 0
public init(receiver:Receiver) {
self.eventReceiver = receiver
}
public func connectTo() {
guard let manager = Connections.shared[self.connectionKey] else { return }
let connection = manager.connection
// disconnect any previous connections
disconnectFrom()
// Connect the connection observer
connectionObserverHandlerID = connection.addConnectionObserver(observer: eventReceiver)
if let variableSet = eventReceiver.variableSet, let handler = eventReceiver.handleVariableUpdates {
eventHandlerID = connection.requestVariables(variables: variableSet, handler: handler)
}
}
public func disconnectFrom(){
guard let manager = Connections.shared[self.connectionKey] else { return }
let connection = manager.connection
// Disconnect
if connectionObserverHandlerID != 0 {
connection.removeConnectionObserver(id: connectionObserverHandlerID)
}
if eventHandlerID != 0 {
connection.unRequestVariables(ident: eventHandlerID)
}
}
}
class ManagedUIView: UIView, ManagedComponent, EventReceiver {
private var component:ManagedComponentImpl<ManagedUIView>!
public var variableSet:Set<VariableID>?
public var handleVariableUpdates:((Set<VariableID>)->Void)?
public override init(frame: CGRect) {
super.init(frame: frame)
component = ManagedComponentImpl<ManagedUIView>(receiver: self)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
component = ManagedComponentImpl<ManagedUIView>(receiver: self)
}
var connectionKey:String {
set {
component.connectionKey = newValue
}
get {
return component.connectionKey
}
}
func connectTo() {
component.connectTo()
}
func disconnectFrom() {
component.disconnectFrom()
}
func notifyState(state: ConnectionState) {}
}
Okay - for everybody reading this, the answers are:
- The problem should probably be solved by a delegate and not by inheritance.
- To avoid inheriting from NSObject: the problem seems to be that protocols can not only be implemented by classes. Therefore the protocol needs a class limitation to work as weak references. As a result ManagedComponentImpl does not need to be generic any more and I can just have a weak CAPEvent receiver optional.

Ambiguous functions in multiple protocol extensions?

I have multiple protocols that have the same function name. Some protocols have associated types, where I can't figure out how to call the functions as I do in non-generic protocols. I get the error: Protocol 'MyProtocol1' can only be used as a generic contraint because it has Self or associated type requirements
Here's what I'm trying to do:
protocol Serviceable {
associatedtype DataType
func get(handler: ([DataType] -> Void)?)
}
struct PostService: Serviceable {
func get(handler: ([String] -> Void)? = nil) {
print("Do something...")
}
}
protocol MyProtocol1: class {
associatedtype ServiceType: Serviceable
var service: ServiceType { get }
}
extension MyProtocol1 {
func didLoad(delegate: Self) {
print("MyProtocol1.didLoad()")
}
}
protocol MyProtocol2: class {
}
extension MyProtocol2 {
func didLoad(delegate: MyProtocol2) {
print("MyProtocol2.didLoad()")
}
}
class MyViewController: UIViewController, MyProtocol1, MyProtocol2 {
let service = PostService()
override func viewDidLoad() {
super.viewDidLoad()
didLoad(self as MyProtocol1) // Error here: Protocol 'MyProtocol1' can only be used as a generic contraint because it has Self or associated type requirements
didLoad(self as MyProtocol2)
}
}
How can I specifically call the function from a generic protocol extension?
It's simple to achieve by turning the protocol into a generic (see below), or by creating a type eraser for these protocols, but this very strongly suggests that you have a design problem and you should redesign your classes and/or extensions. A collision like this suggests strongly that MyStruct is doing too many things itself because it's being pulled in multiple directions by MyProtocol1 and MyProtocol2. There should likely be two objects here instead. (Composition rather than inheritance.)
class MyStruct: MyProtocol1, MyProtocol2 {
let service = PostService()
func prot1Load<T: MyProtocol1>(t: T) {
t.didLoad()
}
func prot2Load<T: MyProtocol2>(t: T) {
t.didLoad()
}
init() {
prot1Load(self)
prot2Load(self)
}
}
To your particular example in the comments, I would use composition rather than inheritance. You're treating protocols like multiple-inheritance, which is almost never right. Instead compose out of things that conform to a protocol.
protocol LoadProviding {
func load()
}
struct MyLoader1: LoadProviding {
func load() {
print("MyLoader1.didLoad()")
}
}
struct MyLoader2: LoadProviding {
func load() {
print("MyLoader2.didLoad()")
}
}
protocol Loader {
var loaders: [LoadProviding] { get }
}
extension Loader {
func loadAll() {
for loader in loaders {
loader.load()
}
}
}
class MyStruct: Loader {
let service = PostService()
let loaders: [LoadProviding] = [MyLoader1(), MyLoader2()]
init() {
loadAll()
}
}
Of course you don't really have to have LoadProviding be a full struct. It could just be a function if that's all you need:
typealias LoadProviding = () -> Void
func myLoader1() {
print("MyLoader1.didLoad()")
}
func myLoader2() {
print("MyLoader2.didLoad()")
}
protocol Loader {
var loaders: [LoadProviding] { get }
}
extension Loader {
func loadAll() {
for loader in loaders {
loader()
}
}
}
class MyStruct: Loader {
let service = PostService()
let loaders: [LoadProviding] = [myLoader1, myLoader2]
init() {
loadAll()
}
}
If you have time to wade through a video on the subject, you may be interested in the Beyond Crusty: Real World Protocols talk from dotSwift. It's about this and similar problems.

Swift implement multiple protocols with a delegate

I'm trying to implement a protocol that itself inherits multiple protocols that both have a delegate member. Is there a clean way to do this without needing different names for the delegate of each protocol?
protocol ProtocolOne {
var delegate: ProtocolOneDelegate?
}
protocol ProtocolTwo {
var delegate: ProtocolTwoDelegate?
}
protocol CombinedProtocol: ProtocolOne, ProtocolTwo {
}
protocol CombinedDelegate: ProtocolOneDelegate, ProtocolTwoDelegte {
}
class ProtocolImpl: CombinedProtocol {
// How can I implement delegate here?
// I've tried the following options without success:
var delegate: CombinedDelegate?
var delegate: protocol<ProtocolOneDelegate, ProtocolTwoDelegate>?
}
You should be able to combine them in one:
var delegate: (ProtocolOneDelegate & ProtocolTwoDelegate)?
You can now use both protocols.
In your code, delegate is just a normal property. You can have multiple protocols declaring a property with the same name and same type, and have a class directly or indirectly implement it.
If different protocols define a property with the same name but different type, you won't be able to make it compile, because the compiler will complain for redeclaration of a property and class not confirming to one of the protocols.
There are 2 possible solution. The most obvious one is to avoid using names having high probability of being used in other protocols - delegate is a typical case. Use a different naming convention, such as protocol1Delegate, dataSourceDelegate, apiCallDelegate, etc.
The 2nd solution consists of replacing properties with methods. For example:
protocol P1 {
func test() -> String?
}
protocol P2 {
func test() -> Int?
}
protocol P3: P1, P2 {
}
class Test : P3 {
func test() -> String? { return nil }
func test() -> Int? { return nil }
}
Swift consider functions with the same parameters list but different return type as overloads. Note however that if 2 protocols use the same function signature (name, parameters and return type), when implementing in the class you will implement that function once - that might be the wanted behavior in some cases, but unwanted in other cases.
A solution might be to use protocol extensions (check extension Combined). The benefit is that Combined only declares delegate and oneDelegate and twoDelegate are computed cross-implementation. Unfortunately, it's a requirement to have the three variables exposed out of the class, that might be inconvenient.
// MARK: - Delegates protocols
protocol OneDelegate {
func oneDelegate(one: One)
}
protocol TwoDelegate {
func twoDelegate(two: Two)
}
protocol CombinedDelegate: OneDelegate, TwoDelegate {
func combinedDelegate(combined: Combined)
}
// MARK: - Model protocols
protocol One: class {
var oneDelegate: OneDelegate? { get }
}
protocol Two: class {
var twoDelegate: TwoDelegate? { get }
}
protocol Combined: One, Two {
var delegate: CombinedDelegate? { get }
}
extension Combined {
var oneDelegate: OneDelegate? {
return delegate
}
var twoDelegate: TwoDelegate? {
return delegate
}
}
// MARK: - Implementations
class Delegate: CombinedDelegate {
func oneDelegate(one: One) {
print("oneDelegate")
}
func twoDelegate(two: Two) {
print("twoDelegate")
}
func combinedDelegate(combined: Combined) {
print("combinedDelegate")
}
}
class CombinedImpl: Combined {
var delegate: CombinedDelegate?
func one() {
delegate?.oneDelegate(self)
}
func two() {
delegate?.twoDelegate(self)
}
func combined() {
delegate?.combinedDelegate(self)
}
}
// MARK: - Usage example
let delegate = Delegate()
let protocolImpl = CombinedImpl()
protocolImpl.delegate = delegate
protocolImpl.one()
protocolImpl.two()
protocolImpl.combined()

Grouping Many Functions in Swift

I've got a conceptual Animal API client class that will interface with a Rest Api below (it may have syntax errors, I'm typing it from my head).
class AnimalApi {
let connectionInfo: ApiConnectionInfo
init(connectionInfo: ApiConnectionInfo) {
self.connectionInfo = connectionInfo
}
func login(username: String, password: String) {
// login stuff
}
func logout() {
// logout stuff
}
func get(url: String) {
}
func post(url: String) {
}
func delete(url: String) {
}
}
// Dogs
extension AnimalApi {
func getAllDogs() -> Dogs {
return get("dogResourceUrl")
}
func deleteDog() { }
func updateDog() { }
}
// Cats
extension AnimalApi {
func getAllCats() { }
func deleteCat() { }
func updateCat() { }
}
Is there a better way to group code in Swift instead of using extensions? There will be dozens of API resources I have to call that are all located on the same API server. I am trying to avoid the following...
let api = AnimalApi()
let dogs = api. // bombarded with all functions here, ideally something like api.Dogs.getAll would be more manageable
I realize that Apple uses extensions to group their code in their Swift API, but is there a better way? Sub classes maybe?
EDIT: I'd like to avoid sub classes if possible. This is because I am planning on having a single global instance of the AnimalApi since it will be accessed throughout the app constantly. Maybe make AnimalAPi members static and have separate classes with static members that contain functions that call the static AnimalApi.
class DogApi {
class func all() { return AnimalApi.get("dogResourceUri") }
}
let dogs = DogApi.all()
The below sample code is an attempt to accomplish your requirement.
Hope it helps.
typealias Task = () -> ()
typealias Api = (getAll: Task, delete: Task, update: Task)
class AnimalApi {
let dogs: Api = {
func getAll() { }
func delete() { }
func update() { }
return (getAll, delete, update)
}()
let cats: Api = {
func getAll() { }
func delete() { }
func update() { }
return (getAll, delete, update)
}()
}
Now you can use it anywhere in the app as follows without getting bombarded with all different functions:
let api = AnimalApi()
let dogs = api.dogs.getAll

Parse PFSubclassing not working with Swift

I have copied the Parse Swift example for Subclassing:
class Armor : PFObject, PFSubclassing {
override class func load() {
self.registerSubclass()
}
class func parseClassName() -> String! {
return "Armor"
}
}
I get the following errors:
/Parse/Armor.swift:11:1: error: type 'Armor' does not conform to protocol 'PFSubclassing'
class Armor : PFObject, PFSubclassing {
^
__ObjC.PFSubclassing:15:28: note: protocol requires function 'object()' with type '() -> Self!'
#objc(object) class func object() -> Self!
^
__ObjC.PFSubclassing:23:52: note: protocol requires function 'objectWithoutDataWithObjectId' with type '(String!) -> Self!'
#objc(objectWithoutDataWithObjectId:) class func objectWithoutDataWithObjectId(objectId: String!) -> Self!
^
__ObjC.PFSubclassing:30:27: note: protocol requires function 'query()' with type '() -> PFQuery!'
#objc(query) class func query() -> PFQuery!
^
__ObjC.PFSubclassing:35:38: note: protocol requires function 'registerSubclass()' with type '() -> Void'
#objc(registerSubclass) class func registerSubclass()
^
/Parse/Armor.swift:14:9: error: 'Armor.Type' does not have a member named 'registerSubclass'
self.registerSubclass()
^ ~~~~~~~~~~~~~~~~
I saw this answer: https://stackoverflow.com/a/24899411/843151 and tried that solution with no luck, I get the same errors.
Any suggestions of why this is happening? Thanks in advance.
I needed to import the parse PFObject+Subclass.h in my Objective-C bridging header
#import <Parse/PFObject+Subclass.h>
With xCode 6.1.1 I was able to get this working without the bridging header. Just:
import Parse
at the top of the module. For the class declaration I did need to use #NSManaged for the variable types to get them to link to the Parse class variables successfully. Like this:
class PSCategory : PFObject, PFSubclassing {
override class func load() {
self.registerSubclass()
}
class func parseClassName() -> String! {
return "Category"
}
#NSManaged var Name: String
}
Then in my query all the names are dynamically linked:
var query = PSCategory.query() // PFQuery(className: "Category")
query.cachePolicy = kPFCachePolicyCacheElseNetwork // kPFCachePolicyNetworkElseCache
query.maxCacheAge = 60 * 60 * 24 // One day, in seconds.
query.findObjectsInBackgroundWithBlock {
(categories: [AnyObject]!, error: NSError!) -> Void in
if error == nil {
for abstractCategory in categories {
let category = abstractCategory as PSCategory
NSLog("Category Name: %#", category.Name)
}
} else {
NSLog("Unable to retrieve categories from local cache or network")
}
}
Parse recommends initialize() instead of load()
class Armor : PFObject, PFSubclassing {
override class func initialize() {
var onceToken : dispatch_once_t = 0;
dispatch_once(&onceToken) {
self.registerSubclass()
}
}
static func parseClassName() -> String! {
return "Armor"
}
}
It appears that PFSubclassing does not currently work correctly in Swift as is, as of v1.7.2, released April 27, 2015.
I was able to get it working by implementing custom getters and setters for properties as a temporary workaround--which somewhat defeats the purpose, but at least this approach will result in only minor refactoring once PFSubclassing is made ready for Swift.
It is not necessary to add #import <Parse/PFObject+Subclass.h> to the bridging header. But, as indicated in the PFSubclassing Protocol Reference, "Warning: This method must be called before [Parse setApplicationId:clientKey:]," you should register all PFObject custom subclasses before calling Parse.setApplicationId(_:, clientKey:).
Here's an example for a custom PFObject subclass called PFChatLOCMessage:
// In ProjectName-Bridging-Header.h
#import <Parse/Parse.h>
// In AppDelegate.swift
#UIApplicationMain
final class AppDelegate: UIResponder, UIApplicationDelegate {
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
configureParse()
return true
}
func configureParse() {
registerParseSubclasses()
Parse.setApplicationId("...", clientKey: "...")
}
func registerParseSubclasses() {
PFChatLOCMessage.registerSubclass()
}
}
// In PFChatLOCMessage.swift
private let PFChatLOCMessageClassName = "PFChatLOCMessage"
private let userKey = "user"
class PFChatLOCMessage: PFObject {
var user: PFUser! {
get { return self[userKey] as! PFUser }
set { self[userKey] = newValue }
}
override init() {
super.init()
}
override init(user: PFUser) {
super.init()
self.user = user
}
}
extension PFChatLOCMessage: PFSubclassing {
class func parseClassName() -> String {
return PFChatLOCMessageClassName
}
}
I got deadlocks / hangs using override class func initialize - even though that's recommended in the parse documentation.
Thinking about it, it's not a good idea to do threading in the init methods of classes - you never know when or in what context these might get called.
This worked for me - for all my custom subclasses, before I call the parse init methods, I explicitly register them as subclasses.
This way the order in which things get called is well defined. Also, it works for me ;)
MyPFObjectSubclass.registerSubclass()
MyPFObjectSubclass2.registerSubclass()
MyPFObjectSubclass3.registerSubclass()
// etc...
let configuration = ParseClientConfiguration {
$0.applicationId = "fooBar"
$0.server = "http://localhost:1337/parse"
}
Parse.initializeWithConfiguration(configuration)