Swift 3: Array.contains(customObject) - ios

I am trying to implement the if block seen below:
if loggedInUser.following.contains(userToView) {
}
where loggedInUser.following is an array of a custom User class and userToView is a single instance of the User class.
class User {
....
}
However, loggedInUser.following.contains(userToView) is throwing the error seen below:
Cannot convert value of type 'User' to expected argument type '(User) throws -> Bool'
I am under the impression I will need to implement some sort of a function that determines if two users are equal, but i have no idea how to implement such a function. Any help would be much appreciated; thank you in advance!

Yo can use the code below
if (loggedInUser.following as NSArray).contains(userToView) {
}

Thank you all for the suggestions.
Everything worked as expected after creating the following function and implementing the "Equatable" Protocol:
class User: Equatable {
//...
var id = Int() //Unique Identifier
//...
}
func ==(lhs: User, rhs: User) -> Bool {
return lhs.id == rhs.id
}
and after implementing the above code i was able to call the following without any problems:
if loggedInUser.following.contains(userToView) {
...
}

Related

Swift Generics & Upcasting

I've got a quick question regarding generics in Swift. The problem is I'm trying to store a variable that takes a generic as a parameter, but am unable to cast it up to the type it is restricted by. It's best explained in a short example:
class Foo { }
class Thing<T: Foo> {
func produceBar() -> Bar {
return Bar(aThing: self as! Thing<Foo>)
}
}
class Bar {
var thing: Thing<Foo>
init(var aThing: Thing<Foo>) {
self.thing = aThing
}
}
The code above produces the error: "Cast from Thing<T> to unrelated type Thing<Foo> always fails"
Shouldn't it never fail, since T is restricted to being a subclass of Foo? I must be misunderstanding the way generics work in Swift, any guidance or help would be much appreciated!
Swift generics are not covariant. That is to say, exactly what the error says: you can't automatically say a Basket<Apple> is a kind of Basket<Fruit> even if Apple is a kind of Fruit. There is good reason for this.
Consider the following code:
class Fruit {}
class Apple: Fruit {}
class Orange: Fruit {}
class Basket<T: Fruit> {
private var items: [T]
func add(item: T) {
items.append(item)
}
init() {}
}
func addItem<T: Fruit>(var basket: Basket<T>, item: T) {
basket.add(item)
}
let basket:Basket<Apple> = Basket()
addItem(basket as Basket<Fruit>, Orange())
This would be legal code if Basket<Apple> were considered a Basket<Fruit>, and I'd be allowed to add an orange to a basket of apples.

Cannot invoke 'handler' with argument list of type '([Post])'

I both do, and don't get why the last line of this playground throws a compiler error:
protocol Model { }
struct Post: Model {
var content = "Hello"
}
struct Posts: Model {
var allPosts: [Post] = [Post(), Post(), Post()]
}
func handler(items: [Model]) { }
var posts = Posts()
handler(posts.posts)
If you're reading between the lines, my goal is to be able to invoke a function with an argument that is an array of structs that conform to a protocol. The function should be able to deal with arrays of different types of structs. Would love to know what I'm missing, and if you have a suggestion for a better solution.
Thanks!
It seems to be Swift limitations. But you can do some workaround like this using Generics:
func handler<T: Model>(items: [T]) { }
or else make your protocol a #objc protocol which you can only apply to class type:
#objc protocol Model { }
class Post: Model {
var content = "Hello"
}

Anonymous inner Class in Swift

In Java I can do the following:
interface SomeCallback {
void onDone();
}
then I can create a function like this:
void test(SomeCallback callback) {
...
}
To call this function I do:
test(new SomeCallback() {
#Override
void done() {
...
}
});
I want to do something similar in Swift. I could create a protocol
protocol SomeCallback : class {
func done()
}
and a function like this
func test(callback: SomeCallback) {
...
}
I am still struggling with the call of this function.
Edit: Since I use an external API which requires a delegate I cannot use a Closure.
Is it possible to create some kind of anonymous inner class like I did it in the Java example to call test()?
Update: If you can't use a closure/function, the direct answer is: no, there are no anonymous inner classes. However, as Mike M points out, you'll have to use a class, and this class may be nested/inner to prevent polluting the global namespace. This class may well have a closure for every method it needs to implement and just call through to those closures.
The Swift-y way of doing this as long as you just need one method is to just use a lambda/closure.
For example, see NSComparator, which is typealiased since it is used all over the place and you are meant to recognize it.
In your example, specifying a function type inline will do fine. So for example:
func test(callback: () -> Void) {
...
callback()
}
// called as:
test({ in
...
})
// or even (since it's the last parameter)
test { in
...
}
Just to clarify the syntax because what you wrote is a little confusing.
#objc protocol SomeCallback {
func done() -> Void
}
No need to inherit from class as you wrote. Also, don't forget the #objc even if you do not want to bridge the protocol to that language. It helps with compiler complaints later on (might be a bug at the moment)
You cannot instantiate a protocol in Swift. You can however have an internal class that inherits from NSObject (root object) and implements this.
class External: NSObject {
class Internal : SomeCallback {
func done() {
// does something
}
}
let int = Internal()
func test(callback : SomeCallback) {
// additional work
callback.done()
}
}

How to reference a class that follows a protocol in return type of function?

I have a protocol called Social Service, declared as follows:
protocol SocialService: class {
class func testFunc()
}
A class that follows the protocol may look like this:
class Twitter: SocialService {
class func testFunc() {
}
}
I want to have a method which returns a class that follows this protocol, so calling it would look like this:
let socialService = socialServiceForServiceType(serviceType: String)
I'm not sure what I need to put as the return value type of this function. For example, this:
func socialServiceForServiceType(serviceType: String) -> SocialService.Type
doesn't give an error right here, but trying to call it as above, gives an error:
Accessing members of protocol type value 'SocialService.Type' is
unimplemented
EDIT: I don't want an instance of that type, I want a class of that type. So I want a Twitter class, so I can call the class methods from the SocialService protocol on it.
Like the error says, this feature is unimplemented. However...
I don't want an instance of that type, I want a class of that type. So I want a Twitter class, so I can call the class methods from the SocialService protocol on it.
I'm not sure what you think you're getting from avoiding instances like this. Bear in mind classes don’t need to have member variables, and without them are essentially just collection of function pointers – which is what you seem to be looking for.
If you implement a Twitter class that has no properties and that conforms to a protocol, then calling methods on that protocol will dynamically dispatch to the implementations of that instance:
protocol SocialService: class {
func testFunc()
}
class Twitter: SocialService {
func testFunc() {
println("Testing Twitter!")
}
}
func socialServiceForServiceType(serviceType: String) -> SocialService {
return Twitter()
}
let service = socialServiceForServiceType("blah")
// prints "Testing Twitter!"
service.testFunc()
If your concern is that you want to put member variables in the Twitter class, but don’t want the overhead of that for some features, then this probably suggests you want to decompose this functionality into two different classes. Alternatively, if you want a singleton instance (to handle the connectivity for example) then there are other patterns to handle this.
Use simply
func socialServiceForServiceType(serviceType: String) -> SocialService
A protocol can be the return type of a function.
Totally agree with Airspeed Velocity, but I'd like to expand on one of his points:
I'm not sure what you think you're getting from avoiding instances like this. Bear in mind classes don’t need to have member variables, and without them are essentially just collection of function pointers – which is what you seem to be looking for.
I assume you're trying to do something like this:
func socialServiceForServiceType(serviceType: String) -> SocialService.Type
...
let cls = socialServiceForServiceType("twitter")
let conn = cls.connect(user)
Or something like that. You don't need classes to achieve that. You can just return functions.
typealias Connect = User -> Connection
func connectorForServiceType(serviceType: String) -> Connect {
switch serviceType {
case "twitter": return Twitter.Connect
...
}
}
let connect = connectorForServiceType("twitter")
let conn = connect(user)
If you have a whole bundle of functions that you want to package together, just use a struct.
struct ServiceHandlers {
let connect : User -> Connection
let ping : () -> Bool
let name: () -> String
}
func standardPinger(host: String) -> () -> Bool {
return { host in
// perform an ICMP ping and return Bool
}
}
func handlersForServiceType(serviceType: String) -> ServiceHandlers {
switch serviceType {
case "twitter":
return ServiceHandlers(connect: Twitter.connect,
ping: standardPinger("www.twitter.com"),
name: { "Twitter" })
...
}
}
let service = handlersForServiceType("twitter")
let conn = service.connect(user)
In some ways this is duplicative with class methods, but (a) the features you need for class methods aren't implemented, and (b) this is much more flexible. You can return any collection of functions you want; they don't have to all be class methods. It's easier to have default behaviors (which are hard in Swift when you use inheritance). It's easier to extend because you don't necessarily have to extend all the classes (see my use of standardPinger, which is some function I've made up that returns another function; it doesn't have to be a class method).
Breaking free of class/inheritance thinking and just passing around functions can be a major benefit in Swift. Sometimes a struct is better than a protocol.
Use a Factory pattern to achieve the same.
class SocialFactory : NSObject
{
class func socialServiceForServiceType(serviceType: String) -> SocialService?
{
switch serviceType
{
case "Twitter":
return Twitter();
case "Facebook":
return Facebook()
default:
return nil;
}
}
}

Accessing the super from global scope

There is a code in Objective C I'm trying to translate using mostly swift and that includes changing the isEqual: function to == operand. The problem is that the code asks me to check the super of the instances being compared but that's impossible from global scope where the operator functions are located.
Is there some other way to migrate this code to swift?
- (BOOL)isEqual:(id)object
{
AAPLCollectionViewGridLayoutAttributes *other = object;
if (![super isEqual:other])
return NO;
return YES;
}
You can split the solution into 2 steps:
1) Define an extension of AAPLCollectionViewGridLayoutAttributes where you override the isEqual method. (Here you can access the super).
extension AAPLCollectionViewGridLayoutAttributes {
public override func isEqual(object: AnyObject!) -> Bool {
// your custom logic will go here
var other = object as AAPLCollectionViewGridLayoutAttributes
return super.isEqual(other)
}
}
2) Overload the == operator simply calling the method defined above.
public func ==(lhs: AAPLCollectionViewGridLayoutAttributes, rhs: AAPLCollectionViewGridLayoutAttributes) -> Bool {
return lhs.isEqual(rhs)
}
Please note that I used the "public" modifier twice, they should be compatible with the access modifier of your class AAPLCollectionViewGridLayoutAttributes.

Resources