Alex Bollbach
Alex Bollbach

Reputation: 4570

Adjusting height of Today App Extension

I have a Today Widget which displaying the upcoming train departures based on a pair of stations chosen in the main application. Given that the departure times changes with time, I have an API call in viewWillAppear fetching the new times and repopulating the cells of a tableView.

Currently, the widget starts off with a height of what looks like 150-200 points in height. My updating logic attempts to set the preferredContent height but this doesn't work. I have the tableView constrained to the top/bottom layout guides. I have tried resetting the tableView's frame height to the main view after telling it a new preferredContent.

Presumably, the callback of my network happens after viewWillAppear, so I invoke layoutIfNeeded to trigger viewDidLayoutSubviews where I reload the tableview.

None of this gets me what I want to see. A tableview populated by the departure times which is N times the height of a cell where N is the number of departure times most recently fetched by my API call.

What am I missing? Any help would be greatly appreciated.

EDIT:

This is the relevant code where I attempt to re-height the extension.

 override func viewWillAppear(_ animated: Bool) {
 
      dao.fetchTrips { (trips) in
        
         self.tripsDataSource.dataStore = trips
 
         let numTrips = trips?.count
         let rowHeight = 44 // static
         let h = numTrips! * rowHeight
         
         self.preferredContentSize = CGSize(width: 0, height: h)
 
         self.view.layoutIfNeeded()
  
      }
      
   }
   
   

   override func viewDidLayoutSubviews() {
      self.tableView.reloadData()
   }

I have noticed viewDidLayoutSubviews is not called after layoutIfNeeded is invoked in the completion handler. Although that may not be the issue, as the app-extension main view does not change after setting a new preferredContentSize.

Upvotes: 0

Views: 766

Answers (1)

e.ozmen
e.ozmen

Reputation: 253

I had the same problem. Few minutes ago I solved it. The default view of widget doesn't show the max height. You need to press show more , next to App title.

Remove your code and just add this to your widget class and on else branch set the height what you want. This will call when you hit show less/ show more.

@available(iOSApplicationExtension 10.0, *)
    func widgetActiveDisplayModeDidChange(_ activeDisplayMode: NCWidgetDisplayMode, withMaximumSize maxSize: CGSize){
        if (activeDisplayMode == NCWidgetDisplayMode.compact) {
            self.preferredContentSize = CGSize(width: 0, height: maxSize.height);
        }
        else {
            self.preferredContentSize = CGSize(width: 0, height: self.tableView.contentSize.height);
        }
    }

Edited: My code:

import UIKit
import NotificationCenter

let groupappname = "group.***.***"


class MyCollectionViewController: UICollectionViewController , NCWidgetProviding,UICollectionViewDelegateFlowLayout {

    var isEmptyData = true
    var array = NSMutableArray()
    var defaults = UserDefaults.init(suiteName: groupappname)!

    override func viewDidLoad() {
        super.viewDidLoad()


        if #available(iOSApplicationExtension 10.0, *) {
            self.extensionContext?.widgetLargestAvailableDisplayMode = NCWidgetDisplayMode.expanded
        } else {
            // Fallback on earlier versions
        }


        registerObserver()
        refreshData()

    }
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        removeObserver()
    }

    func refreshData(){

        self.preferredContentSize = (self.collectionView?.contentSize)!
        #somecode
        self.collectionView?.reloadData()
    }

    func refreshData_NoData(){
        self.preferredContentSize = (self.collectionView?.contentSize)!
        self.collectionView?.reloadData()
    }
    func widgetPerformUpdate(completionHandler: @escaping (NCUpdateResult) -> Void) {
        print("widgetperformupdate")
        completionHandler(NCUpdateResult.newData)
    }
    @available(iOSApplicationExtension 10.0, *)
    func widgetActiveDisplayModeDidChange(_ activeDisplayMode: NCWidgetDisplayMode, withMaximumSize maxSize: CGSize){
        if (activeDisplayMode == NCWidgetDisplayMode.compact) {
            self.preferredContentSize = CGSize(width: 0, height: maxSize.height)
        }
        else {
            self.preferredContentSize = CGSize(width: 0, height: (self.collectionView?.contentSize.height)!)
        }
    }


    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


    // MARK: UICollectionViewDataSource

    override func numberOfSections(in collectionView: UICollectionView) -> Int {
        // #warning Incomplete implementation, return the number of sections
        return 1
    }


    override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        // #warning Incomplete implementation, return the number of items

        return array.count
    }
    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

        #somecode
        self.preferredContentSize = collectionView.contentSize

        return cell
    }


}

Upvotes: 1

Related Questions