#StackBounty: #ios #swift #uicollectionview Incomplete delete animation for a single row horizontal UICollectionView with UICollectionV…

Bounty: 500

Currently, I have a single row horizontal UICollectionView with UICollectionViewCompositionalLayout

[All] [Calendar] [Home2] [Work3] [Work4] ... [Work8] [⚙]

The UICollectionView, is acting as a scrollable Tab layout navigation bar.

When user switch to [⚙] page, he is able to delete the tab before itself. In this case, during the 1st time of the delete operation, tab [Work8] will be removed.

Here’s the straightforward code to achieve so.


https://github.com/yccheok/ios-tutorial/blob/debug/TabDemo/TabDemo/ViewController.swift#L144

func debug() {
    if tabInfos.count < 2 {
        return
    }
    
    let index = tabInfos.count-2
    tabInfos.remove(at: index)
    let indexPath = getIndexPath(index)
    self.tabCollectionView.deleteItems(at: [indexPath])
    
    // TODO: Possible solution.
    /*
    self.tabCollectionView.reloadData()
    DispatchQueue.main.async() {
        let indexPath = self.getIndexPath(self.tabInfos.count-1)
        self.tabCollectionView.selectItem(at: indexPath, animated: false, scrollPosition: .centeredVertically)
        self.tabCollectionView.scrollToItem(at: indexPath, at: .right, animated: true)
    }
     */

    // Clear left/ right cached view controllers - https://stackoverflow.com/a/21624169/72437
    pageViewController.dataSource = nil
    pageViewController.dataSource = self

    // Don't forget to adjust the selection index.
    if index < self.selectedTabInfoIndex {
        selectedTabInfoIndex -= 1
    }
}

Strange outcome

https://www.youtube.com/watch?v=Wzgb4QErUes (Please refer to this video for complete deletion animation)

This is how it looks like before deletion

enter image description here

As you can see in the video, after the deletion of [Work8], the left side tab ([Work3]) is not visible

enter image description here

My expected outcome is, [Work3] should be visible too immediately, without any additional action from user. I need to tap on the UICollectionView, move it abit, only all the tabs will appear

enter image description here


I prefer not to use reloadData, as

  1. It will not preserve scroll position of UICollectionView.
  2. It does not have animation.

Do you have any idea what is the root cause of this strange animation outcome?

Here’s the complete source code to try it out – https://github.com/yccheok/ios-tutorial/releases/tag/debug


Get this bounty!!!

#StackBounty: #ios #swift #xcode #audio #audio-recording How to record audio with a certain threshold filter in swift

Bounty: 50

enter image description here

I need to add this functionality in one of my app in swift, I want the user to adjust the threshold and so it’ll be only recorded when it crosses the limit set by the user and stop automatically or in a given time when the user stops.

It would be great if you can share your expertise in how to collect all the data in one file like when a user will pause and continue it’ll keep all the audio in one file.

I actually have no idea about this and will truly appreciate any kind of feedback.

Thanks.


Get this bounty!!!

#StackBounty: #ios #swift #multithreading #concurrency Safety of using an empty reference instance across multiple threads

Bounty: 150

Background

I have a class Data that stores multiple input parameters and a single output value.

The output value is recalculated whenever one of the input parameters is mutated.

The calculation takes a non-trivial amount of time so it is performed asynchronously.

If one of the input parameters changes during recalculation, the current calculation is cancelled, and a new one is begun.

The cancellation logic is implemented via a serialized queue of calculation operations and a key (reference instance) (Data.key). Data.key is set to a new reference instance every time a new recalculation is added to the queue. Also only a single recalculation can occur at a time — due to the queue. Any executing recalculation constantly checks if it was the most recently initiated calculation by holding a reference to both the key that what was created with it when it was initiated and the currently existing key. If they are different, then a new recalculation has been queued since it began, and it will terminate.

This will trigger the next recalculation in the queue to begin, repeating the process.

The basis for my question

The reassignment of Data.key is done on the main thread.

The current calculation constantly checks to see if its key is the same as the current one. This means another thread is constantly accessing Data.key.

Question(s)

Is it safe for me to leave Data.key vulnerable to being read/written to at the same time?

Is it even possible for a property to be read and written to simultaneously?


Get this bounty!!!

#StackBounty: #ios #swift #macos #coreml NLTagger: enumerating tags of multiple types in one pass

Bounty: 200

Using the NLTagger class, I’m wondering if anyone can recommend the most straightforward way to enumerate through the tagged tokens in a given text, but pulling out multiple tag types per token. For example, to enumerate the words in a given text, pulling out (lemma, lexical category) for each.

It seems that the enumerateTags() method and associated NLTag class have the limitation of only reporting one particular tag type per enumeration. So I can achieve what I want by making multiple passes over the text, e.g. pulling out the string ranges that match given criteria on the first pass and then matching things up on later passes. For example, I could lemmatise all of the nouns and verbs like this:

let tagger = NLTagger(tagSchemes: [.lemma, .nameTypeOrLexicalClass])
tagger.string = //some text
let keyWordCategories: [NLTag] = [.noun, .verb]
let options: NLTagger.Options = [.omitPunctuation, .omitWhitespace, .joinNames]

// In the first pass, we're going to record which ranges are of categories we're interested in
var keywordRanges = Set<Range<String.Index>>(minimumCapacity: 200)

// First pass: which are the nouns and verbs?
tagger.enumerateTags(in: text.startIndex..<text.endIndex, unit: .word, scheme: .nameTypeOrLexicalClass, options: options) { tag, tokenRange in
    if let tag = tag {
        if (keyWordCategories.contains(tag)) {
            keywordRanges.insert(tokenRange)
        }
    }
    return true
}

// Second pass: lemmatise, filtering on just the nouns and verbs
tagger.enumerateTags(in: text.startIndex..<text.endIndex, unit: .word, scheme: .lemma, options: options) { tag, tokenRange in
    if let tag = tag {
        if (keywordRanges.contains(tokenRange)) {
            lemmas.insert(tag.rawValue)
        }
    }
    return true
}

This mechanism achieves the desired functionality, but strikes me as a somewhat clumsy and potentially inefficient way to have to go about things. I would have expected to be able to enumerate (lemma, lexical category) in a single pass. I’m assuming that the NLTagger instance caches things behind the scenes so that it’s not as terrible as it looks in terms of efficiency. But it’s still far from ideal in terms of simplicity of the code. Can anyone more familiar with this API advise on whether this is really the intended pattern?


Get this bounty!!!

#StackBounty: #json #swift #xml #augmented-reality #arkit ARKit 4.0 – Is it possible to convert ARWorldMap data to JSON file?

Bounty: 50

I’d like to know whether it is possible to convert a worldMap binary data (that stores a space-mapping state and set of ARAnchors) to json or xml file?

func writeWorldMap(_ worldMap: ARWorldMap, to url: URL) throws {

    let data = try NSKeyedArchiver.archivedData(withRootObject: worldMap, 
                                         requiringSecureCoding: true)
    try data.write(to: url)
}

If this possible, what tools can I use for that?


Get this bounty!!!

#StackBounty: #swift #uitableview #border #cell Wallet style with multiple cells border Swift

Bounty: 50

How do I make only the last cell with round corner and black border color? and the rest of the cell will only have left and right border?

This is the design of the cell. The pink part is the section header, the white part is the cell. In the image I have 6 cells and I want the 6th one to have round corner and black border. Cell 1-5 will only have left and right border.

My tableview will contain few sets of todo please see the image under.

Thank you.

enter image description here

enter image description here

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
         .    
         .
         .

    cell.view.clipsToBounds = true

    if indexPath.row == todoList.count - 1 {
        cell.view.layer.cornerRadius = 10
        cell.view.layer.maskedCorners = [.layerMinXMaxYCorner,.layerMaxXMaxYCorner]
        cell.view.layer.borderColor = UIColor.black.cgColor   //not working it makes all cell has border
        cell.view.layer.borderWidth = 1
       
    } else {
        //only want left and right with black border
    }
        .    
        .
        .
}


Get this bounty!!!

#StackBounty: #ios #swift #wkwebview #swift5 Tracking navigation in WKWebView doesn't work always

Bounty: 250

I am trying to catch a button click in my web view. Button "action" if I can say so, triggers certain url… I am not really able to catch this moment through WKNavigationDelegate. webview is set like this:

 lazy var advertWebKitView: WKWebView = {
        let webConfiguration = WKWebViewConfiguration()
        let preferences = WKPreferences()
        preferences.javaScriptEnabled = true
        webConfiguration.preferences = preferences
        let webView = WKWebView(frame: .zero, configuration: webConfiguration)

        webView.navigationDelegate = self
        webView.uiDelegate = self
        webView.translatesAutoresizingMaskIntoConstraints = false
        return webView
    }()

I am trying to catch that button click like this:

 func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
        decisionHandler(.allow)
        guard let urlAsString = navigationAction.request.url?.absoluteString.lowercased() else {
            return
        }
        
        if urlAsString.range(of: "...") != nil {
           
        }
    }

but this method doesn’t trigger when button is clicked.

On android, it works and its done like this:

@Override
        public void doUpdateVisitedHistory(WebView view, String url, boolean isReload) {
            if (url.equals("...")) {
                finish();
            }
             //...
            super.doUpdateVisitedHistory(view, url, isReload);
        }

what would be equal method and a way to track navigation correctly through wkwebview?

EDIT:
if there is some info needed about the webpage structure or so, please ask for details and I will add that too. I just didn’t know which info may be relevant or helpful.


Get this bounty!!!

#StackBounty: #ios #swift #xcode #segue Manual (automatic) Segue not working – table view cell

Bounty: 400

I’m new to Xcode and I’m following the tutorial here which goes through how to add a manual segue.

https://github.com/AdditionAddict/learnXcode

Problem: When clicking on a table cell in the simulator the manual segue is not triggered.

What I’ve tried: I’ve added a manual (automatic) segue, an identifier, and whilst the tutorial says as this point a selection of a cell with result in going from the table view cell to the meal detail scene, I’ve continued to the code part and my breakpoint in prepare still does not trigger.

    // MARK: - Navigation

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        super.prepare(for: segue, sender: sender)
        
        switch(segue.identifier ?? "") {
            
        case "AddItem":
            os_log("Adding a new meal", log: OSLog.default, type: .debug)
            
        case "ShowDetail":
            // set the meal for the `MealViewController` as the meal selected in the `MealTableViewController`
            os_log("Show detail of a meal", log: OSLog.default, type: .debug)
            
            guard let mealDetailViewController = segue.destination as? MealViewController else {
                fatalError("Unexpected destination, (segue.destination)")
            }
            guard let selectedMealCell = sender as? MealTableViewCell else {
                fatalError("Unexpected sender, (String(describing: sender))")
            }
            guard let indexPath = tableView.indexPath(for: selectedMealCell) else {
                fatalError("The selected cell is not being displayed by the table")
            }
            
            let selectedMeal = meals[indexPath.row]
            mealDetailViewController.meal = selectedMeal
            
        default:
            fatalError("Unexpected Segue Identifier")
        }
    }

Checks made:
If, for the purposes of debugging only, I put the following in my MealTableViewController.swift with a breakpoint nothing happens when I click a table cell:

    override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
        return true
    }

This makes me think the table cells aren’t registering a ‘selection’.

Table View Selection property is Single Selection.

The custom MealTableViewCell has User Interaction Enabled checked.

Clicking the MealTableViewCell in the outline pane and selecting the Connections inspector in the utilities pane also shows the segue:

Connections Inspector showing segue

Final bits: Is it still possible to add a manual (automatic) segue?
Tutorial is in archive and I’ve managed to follow most of it with small changes.
Using Xcode 11.6

main.storyboard and Identity Inspector

Edit(s) / answers to comment questions:

  1. added (automatic) to manual. I mean the method the tutorial uses from table cell to meal detail.
  2. There isn’t anything in front of the table (that I’m aware of) such as a tap gesture recogniser
  3. The Plus segue works and triggers the prepare unlike clicking a table cell


Get this bounty!!!

#StackBounty: #swift #game-center #gamekit #ios14 #gkmatchmaker Cannot send data using GKMatch.sendData(toAllPlayers:, with: ) in IOS 14

Bounty: 50

I am writing a multiplayer game. I am trying to send data from a player to other using below methods

match.send(data, to: [player], dataMode: .reliable)
match.sendData(toAllPlayers: data, with: .reliable)

It works fine on ios 13 but on ios 14 (Beta 2), I see below message

[Error] WARNING: -[GKMatch sendData:toPlayers:dataMode:error:] is
obsoleted. Game Center doesn’t invoke this obsoleted method from
iOS/tvOS 14.0 and macOS 10.16 onwards


Get this bounty!!!

#StackBounty: #ios #swift Images not going straight into array

Bounty: 50

I have a small problem with some code here. I am trying to populate a collection view with Five Names, descriptions and Images.

I am able to successfully to download all of the above into their respected arrays.

The problem is that the first time I perform the segue the image array has zero values in it. Then I go back a page and re-enter the page to find that all of the arrays have been populated successfully….

This is really annoying. Here is my code:

//arrays of names, descriptions and images
    var names:[String] = []
    var descriptions: [String] = []
    var imagesArray: [UIImage] = []

Heres where I get the images:

func downloadImages(){
        for x in 1...5{
            
            let url = URL(string: "https://www.imagesLocation.com/(x).png")
            
            let task = URLSession.shared.dataTask(with: url!){(data, response, error) in
                
                guard
                    let data = data,
                    let newImage = UIImage(data: data)
                    else{
                        print("Could not load image from URL: ",url!)
                        return
                }
                
                DispatchQueue.main.async {
                    self.imagesArray.append(newImage)
                }
            }
            
            task.resume()
        }
        
        loadDataFromFirebase()
    }
    

Heres where I download the Names and Descriptions from:

 func loadDataFromFirebase() {
        // Fetch and convert data
        let db = Firestore.firestore()
        db.collection(self.shopName).getDocuments { (snapshot, err) in
            if let err = err {
                print("Error getting documents: (err)")
                return
            } else {
                for document in snapshot!.documents {
                    let name = document.get("Name") as! String
                    let description = document.get("Description") as! String
                    self.names.append(name)
                    self.descriptions.append(description)
                }
                self.setupImages() //safe to do this here as the firebase data is valid
            }
        }
    }

Heres where I setup the collection view with the Names, Description and Images array contents:

func setupImages(){
    
    do {
        if imagesArray.count < 5 || names.count < 5  || descriptions.count < 5 {
            throw MyError.FoundNil("Something hasnt loaded")
        }
        
        self.pages = [
            Page(imageName: imagesArray[0], headerText: names[0], bodyText: descriptions[0]),
            
            Page(imageName: imagesArray[1], headerText: names[1], bodyText: descriptions[1]),
            
            Page(imageName: imagesArray[2], headerText: names[2], bodyText: descriptions[2]),
            
            Page(imageName: imagesArray[3], headerText: names[3], bodyText: descriptions[3]),
            
            Page(imageName: imagesArray[4], headerText: names[4], bodyText: descriptions[4]),
        ]
    }
    catch {
        print("Unexpected error: (error).")
    }
}

As you can see from the image below, every array is populating successfully apart from the images array:

enter image description here

Any help is welcome 🙂


Get this bounty!!!