1

I'm trying to implement Native Express Ads in my iOS Project, with swift.

First of all I have a class

class Events {
  var _eventName: String!
  var _realDate: Date!

    var realDate: Date {
        if _realDate == nil {
            _realDate = nil
        }
        return _realDate
    }

    var eventName: String {
        if _eventName == nil {
            _eventName = ""
        }
        return _eventName
    }

//...
}

Which class is getting a JSON from internet and it fills out a tableview. Also i have some functions with this like Searching through the names of the events and also i have a button that filters events by date. All these are working fine with the code below

var eventData = [Events]()
var filteredEvents = [Events]()

eventData.sort() { $0.realDate < $1.realDate }

    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
        filteredEvents = eventData.filter { events in
            return events.eventName.lowercased().contains(searchText.lowercased())
        }

So While i followed the example of the native express ads from here and here

First of all i changed

var eventData = [Events]()
var filteredEvents = [Events]()

to

var eventData = [AnyObject]()
var filteredEvents = [AnyObject]()

So the ads can be appended to the array as i show below in the function addNativeExpressAds()! I have issues with the functions sort() and the filter.

for the sort() it says Value of type 'AnyObject' has no member 'realDate'

and for filter it says Value of type 'AnyObject' has no member 'eventName'

Update 1. After some research on google i found out this could be a solution for sort() function

eventData.sort() { (($0 as! Events).realDate ) < ($1 as! Events).realDate }

Although the eventData Array also includes GADNativeExpressAdView since in the example that i have linked above there is this block of code that downloads the express native ads and appends them to the AnyObject Array eventData see below

func addNativeExpressAds() {
    var index = adInterval
    // Ensure subview layout has been performed before accessing subview sizes.
    nearMeTable.layoutIfNeeded()
    while index < eventData.count {
        let adSize = GADAdSizeFromCGSize(
            CGSize(width: nearMeTable.contentSize.width, height: adViewHeight))
        guard let adView = GADNativeExpressAdView(adSize: adSize) else {
            print("GADNativeExpressAdView failed to initialize at index \(index)")
            return
        }
        adView.adUnitID = adUnitID
        adView.rootViewController = self
        adView.delegate = self


        eventData.insert(adView, at: index) //here it inserts the ads
        adsToLoad.append(adView)
        loadStateForAds[adView] = false

        index += adInterval
    }
}

and by this I get the error

Could not cast value of type 'GADNativeExpressAdView' (0x10046ebd8) to 'Events_Near_Me.Events' (0x10046fb90).

So i can't sort the array of any object cause the GADNativeExpressAdView ads inside my array.

Any idea about this one?

Konstantinos Natsios
  • 2,874
  • 9
  • 39
  • 74
  • 1
    Not related but properties with backing instance variables to get constants is ridiculous in Swift. Just write `let realDate: Date, let eventName: String` and **write an initializer**. Second of all: If you want to combine two different types in an array, write a protocol that both types conform to and use the protocol as type rather than `AnyObject` which is always the worse way. – vadian Jul 04 '17 at 15:05
  • @vadian hey! there is an initilizer although I didn't write down the whole `class`. About the `Protocol` could you give me an example if you can? – Konstantinos Natsios Jul 04 '17 at 15:08
  • Unfortunately there is no information how `GADNativeExpressAdView` and `Events` are related. – vadian Jul 04 '17 at 15:11
  • @vadian if its the worst way to proceed making the array as `AnyObjects` why Google says in their example to do so... I've asked them at their groupd and they don't answer... too bad – Konstantinos Natsios Jul 04 '17 at 15:19
  • [This answer](https://stackoverflow.com/a/30761903/3687801) or [Another answer](https://stackoverflow.com/a/32975891/3687801) might help you. – nayem Jul 04 '17 at 15:21
  • 2
    Maybe the Google guys translated their code literally form Objective-C to Swift without taking advantage of the Swift special features. The weird backing instance variables look pretty much like *google translate* ;-) – vadian Jul 04 '17 at 15:25
  • Google translate!!! LOL @vadian – nayem Jul 04 '17 at 15:27
  • @nayem those examples that you sended, they have the same type of variable inside their class. In my case, GADNativeExpressAdView has no date ! – Konstantinos Natsios Jul 04 '17 at 15:38
  • 1
    Yes I know. But I just tried to show you alternatives. One of them ([this](https://stackoverflow.com/a/30761903/3687801)) implements `protocol` that was suggested by vadian. – nayem Jul 04 '17 at 15:41

1 Answers1

2

First of all in your sort function you force a cast ! to an Event type but your array does not only contain Event object only. So you force the cast and your code fails.

eventData.sort { (first, second) in  
    if let first = first as? Event,
        let second = second as? Event {
        return first.realDate < second.realDate
    }
    if let fist = first as? GADNativeExpressAdView,
        let second = second as? GADNativeExpressAdView {
        return \\ compare?
    }

    return false
}

This is a sample code, I haven't tested it to see if it works as expected but it should give you an idea on how to proceed.

P.S. I do not think it is a good practice to mix your data with views. You should keep your array clean of views and have it only contain data.

gkaimakas
  • 574
  • 3
  • 17