Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Mobile and Embedded
  4. HowTo get Photos from iOS assets-library sorted by lastModified ?

HowTo get Photos from iOS assets-library sorted by lastModified ?

Scheduled Pinned Locked Moved Solved Mobile and Embedded
iosassets-libraryphotosimagepickermultiselection
10 Posts 2 Posters 3.6k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • ekkescornerE Offline
    ekkescornerE Offline
    ekkescorner
    Qt Champions 2016
    wrote on last edited by
    #1

    no problem to get the assets-library - directory and iterate over entries

    QDir theDir = QDir("assets-library://");
    QFileInfoList entryList = theDir.entryInfoList();
    for (int i = 0; i < entryList.size(); ++i) {
        QFileInfo fileInfo = entryList.at(i);
    	// fileInfo.filePath() is something like this:
    	// "assets-library://asset/asset.JPG?id=01DC0CE7-0A57-4B42-BF2E-9A5719D04E1D&ext=JPG" 
    

    having access to the Photos from QML or C++ and display as Image - no problem

    unfortunately the Photos are not sorted
    fileInfo.lastModified() and fileInfo.created() from QFileInfo are empty, so I cannot do a sort from C++

    I know that there's a way to use the native iOS ImagePicker:

    import Qt.labs.platform 1.0
    // hint: also tried FileDialog from QtQuick.Dialogs 1.2
    // but J-P told me QtQuick.Dialogs FileDialog is a 'Monster' - I should use from labs.platform
    FileDialog {
        fileMode: FileDialog.OpenFiles
        property var standardPicturesLocations: StandardPaths.standardLocations(StandardPaths.PicturesLocation)
        folder: standardPicturesLocations[standardPicturesLocations.length - 1]
    }
    

    but this native Picker only allows us to pick single Photos
    https://bugreports.qt.io/browse/QTBUG-67874

    But I need multi-selection of files, so I created a GridView to preview thumbnails and to select one or more. This works fine but users are complaining that the Photos are not sorted.

    Seems I need som iOS native code to get a sorted Array of Pathes to Photos from assets-library.
    Looked at StackOverFlow and found nothing I really understand with less knowledge on native iOS / Obj-C development.

    Anyone has solved this or any ideas HowTo get the list of Photos from iOS sorted ?

    (will provide the solution together with my nearly ready-to-go QML Camera App for Android / iOS)

    THANKS

    ekke ... Qt Champion 2016 | 2024 ... mobile business apps
    5.15 --> 6.8 https://t1p.de/ekkeChecklist
    QMake --> CMake https://t1p.de/ekkeCMakeMobileApps

    1 Reply Last reply
    0
    • SGaistS SGaist

      Sorry, I lost track of the thread.

      Glad you found out !

      ekkescornerE Offline
      ekkescornerE Offline
      ekkescorner
      Qt Champions 2016
      wrote on last edited by ekkescorner
      #8

      @SGaist here's my solution

      .pro:

      ios {
          LIBS += -framework Photos
      

      cpp: (.mm)

      #import <Photos/Photos.h>
      
      const int MEDIA_PHOTOS = 1;
      const int MEDIA_VIDEOS = 2;
      #pragma unused (MEDIA_VIDEOS)
      const QString MEDIA_PHOTO_SUFFIX = "JPG";
      const QString MEDIA_VIDEO_SUFFIX = "MP4";
      ...
      QVariantMap IosUtil::fetchAssets(const int mediaType)
      {
          QVariantMap albumsWithSortedAssetsMap;
          QMap<QDateTime, QString> assetsMap;
          // get the smart albums
          PHFetchResult *smartAlbums = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
          for (NSUInteger i = 0; i < smartAlbums.count; i++) {
              PHAssetCollection *assetCollection = smartAlbums[i];
              // the smart album name
              QString theAlbum = QString::fromNSString(assetCollection.localizedTitle);
      
              // get photo collections for this album
              PHFetchResult *assetsFetchResult = [PHAsset fetchAssetsInAssetCollection:assetCollection options:nil];
      
              // to get it sorted by modificationDate we use a Map
              assetsMap.clear();
      
              // get the Assets (Photos or Videos)
              for (NSUInteger x = 0; x < assetsFetchResult.count; x ++) {
                  PHAsset *asset = assetsFetchResult[x];
                  int mt = asset.mediaType;
                  if(mt != mediaType) {
                      continue;
                  }
                  QString theSuffix;
                  if(mediaType == MEDIA_PHOTOS) {
                      theSuffix = MEDIA_PHOTO_SUFFIX;
                  } else {
                      theSuffix = MEDIA_VIDEO_SUFFIX;
                  }
                  QDateTime modificationDate = QDateTime::fromNSDate(asset.modificationDate);
      
                  // now constructing the URL
                  // https://stackoverflow.com/questions/42579544/ios-phassetcollection-localizedtitle-always-returning-english-name
                  // https://stackoverflow.com/questions/28887638/how-to-get-an-alasset-url-from-a-phasset
                  // AF3C1B68-222B-43D3-9478-53097429F1B2/L0/001 becomes
                  // assets-library://asset/asset.JPG?id=AF3C1B68-222B-43D3-9478-53097429F1B2&ext=JPG
                  QString theId = QString::fromNSString(asset.localIdentifier);
                  QString theUrl = "assets-library://asset/asset.";
                  theUrl.append(theSuffix).append("?id=");
                  theUrl.append(theId.split('/').first());
                  theUrl.append("&ext=").append(theSuffix);
                  // qDebug() << "URL: " << theUrl;
      
                  assetsMap.insert(modificationDate, theUrl);
              } // assets in collection
      
              // now we can fill our list of assets-URLs (sorted descendend by modificationDate)
              QStringList sortedAssetsList;
              QMapIterator<QDateTime, QString> assetsIterator(assetsMap);
              assetsIterator.toBack();
              while (assetsIterator.hasPrevious()) {
                  assetsIterator.previous();
                  sortedAssetsList.append(assetsIterator.value());
              }
      
              // insert sorted list of URLLs into albums map
              albumsWithSortedAssetsMap.insert(theAlbum, sortedAssetsList);
      
          } // media collections in smart album
          // now we have all albums sorted by album name together with sorted collections of assets, where the newest comes first
          return albumsWithSortedAssetsMap;
      }
      

      Good to know: if you fetch the assets, then switch to iOS Camera and create new Photos or delete Photos, go back to your App and again call the same method to fetch assets you’ll get the old content. I had to create a new instance of my IosUtil class to be able to get the newest data from Phto Library.

      ekke ... Qt Champion 2016 | 2024 ... mobile business apps
      5.15 --> 6.8 https://t1p.de/ekkeChecklist
      QMake --> CMake https://t1p.de/ekkeCMakeMobileApps

      1 Reply Last reply
      5
      • SGaistS Offline
        SGaistS Offline
        SGaist
        Lifetime Qt Champion
        wrote on last edited by
        #2

        Hi,

        Can you also share the stack overflow answers that could be useful ? It might be easier with several pair of eyes to get something up and running.

        Interested in AI ? www.idiap.ch
        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

        ekkescornerE 2 Replies Last reply
        0
        • SGaistS SGaist

          Hi,

          Can you also share the stack overflow answers that could be useful ? It might be easier with several pair of eyes to get something up and running.

          ekkescornerE Offline
          ekkescornerE Offline
          ekkescorner
          Qt Champions 2016
          wrote on last edited by
          #3

          @SGaist good idea. will add this later today or tomorrow.

          ekke ... Qt Champion 2016 | 2024 ... mobile business apps
          5.15 --> 6.8 https://t1p.de/ekkeChecklist
          QMake --> CMake https://t1p.de/ekkeCMakeMobileApps

          1 Reply Last reply
          0
          • SGaistS SGaist

            Hi,

            Can you also share the stack overflow answers that could be useful ? It might be easier with several pair of eyes to get something up and running.

            ekkescornerE Offline
            ekkescornerE Offline
            ekkescorner
            Qt Champions 2016
            wrote on last edited by
            #4

            @SGaist here's what I found in StackOverFlow

            https://stackoverflow.com/questions/7977664/sort-files-by-creation-date-ios#
            don't know if this would work with assets (Photos)

            --
            https://stackoverflow.com/questions/30602830/phfetchresult-get-all-photos-and-sort-by-date-inconsistent/30603715
            seems this does what I want, but how to implement that in a way toget an array of pathes for the Photos

            --
            would be cool if someone has an idea HowTo combine this with Qt C++ to get a sorted list of pathes from "assets-library://"
            and what must be put into .h and what into .mm to call it from Qt

            thanks for any tips and hints

            ekke ... Qt Champion 2016 | 2024 ... mobile business apps
            5.15 --> 6.8 https://t1p.de/ekkeChecklist
            QMake --> CMake https://t1p.de/ekkeCMakeMobileApps

            ekkescornerE 1 Reply Last reply
            0
            • ekkescornerE ekkescorner

              @SGaist here's what I found in StackOverFlow

              https://stackoverflow.com/questions/7977664/sort-files-by-creation-date-ios#
              don't know if this would work with assets (Photos)

              --
              https://stackoverflow.com/questions/30602830/phfetchresult-get-all-photos-and-sort-by-date-inconsistent/30603715
              seems this does what I want, but how to implement that in a way toget an array of pathes for the Photos

              --
              would be cool if someone has an idea HowTo combine this with Qt C++ to get a sorted list of pathes from "assets-library://"
              and what must be put into .h and what into .mm to call it from Qt

              thanks for any tips and hints

              ekkescornerE Offline
              ekkescornerE Offline
              ekkescorner
              Qt Champions 2016
              wrote on last edited by
              #5

              @ekkescorner anyone ideas ?
              otherwise next week I have to start fighting with Obj-C to make it work ;-)

              ekke ... Qt Champion 2016 | 2024 ... mobile business apps
              5.15 --> 6.8 https://t1p.de/ekkeChecklist
              QMake --> CMake https://t1p.de/ekkeCMakeMobileApps

              ekkescornerE 1 Reply Last reply
              0
              • ekkescornerE ekkescorner

                @ekkescorner anyone ideas ?
                otherwise next week I have to start fighting with Obj-C to make it work ;-)

                ekkescornerE Offline
                ekkescornerE Offline
                ekkescorner
                Qt Champions 2016
                wrote on last edited by
                #6

                figured it out to get iOS Photos sorted for multi-select. will provide src later

                ekke ... Qt Champion 2016 | 2024 ... mobile business apps
                5.15 --> 6.8 https://t1p.de/ekkeChecklist
                QMake --> CMake https://t1p.de/ekkeCMakeMobileApps

                1 Reply Last reply
                1
                • SGaistS Offline
                  SGaistS Offline
                  SGaist
                  Lifetime Qt Champion
                  wrote on last edited by
                  #7

                  Sorry, I lost track of the thread.

                  Glad you found out !

                  Interested in AI ? www.idiap.ch
                  Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                  ekkescornerE 1 Reply Last reply
                  0
                  • SGaistS SGaist

                    Sorry, I lost track of the thread.

                    Glad you found out !

                    ekkescornerE Offline
                    ekkescornerE Offline
                    ekkescorner
                    Qt Champions 2016
                    wrote on last edited by ekkescorner
                    #8

                    @SGaist here's my solution

                    .pro:

                    ios {
                        LIBS += -framework Photos
                    

                    cpp: (.mm)

                    #import <Photos/Photos.h>
                    
                    const int MEDIA_PHOTOS = 1;
                    const int MEDIA_VIDEOS = 2;
                    #pragma unused (MEDIA_VIDEOS)
                    const QString MEDIA_PHOTO_SUFFIX = "JPG";
                    const QString MEDIA_VIDEO_SUFFIX = "MP4";
                    ...
                    QVariantMap IosUtil::fetchAssets(const int mediaType)
                    {
                        QVariantMap albumsWithSortedAssetsMap;
                        QMap<QDateTime, QString> assetsMap;
                        // get the smart albums
                        PHFetchResult *smartAlbums = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
                        for (NSUInteger i = 0; i < smartAlbums.count; i++) {
                            PHAssetCollection *assetCollection = smartAlbums[i];
                            // the smart album name
                            QString theAlbum = QString::fromNSString(assetCollection.localizedTitle);
                    
                            // get photo collections for this album
                            PHFetchResult *assetsFetchResult = [PHAsset fetchAssetsInAssetCollection:assetCollection options:nil];
                    
                            // to get it sorted by modificationDate we use a Map
                            assetsMap.clear();
                    
                            // get the Assets (Photos or Videos)
                            for (NSUInteger x = 0; x < assetsFetchResult.count; x ++) {
                                PHAsset *asset = assetsFetchResult[x];
                                int mt = asset.mediaType;
                                if(mt != mediaType) {
                                    continue;
                                }
                                QString theSuffix;
                                if(mediaType == MEDIA_PHOTOS) {
                                    theSuffix = MEDIA_PHOTO_SUFFIX;
                                } else {
                                    theSuffix = MEDIA_VIDEO_SUFFIX;
                                }
                                QDateTime modificationDate = QDateTime::fromNSDate(asset.modificationDate);
                    
                                // now constructing the URL
                                // https://stackoverflow.com/questions/42579544/ios-phassetcollection-localizedtitle-always-returning-english-name
                                // https://stackoverflow.com/questions/28887638/how-to-get-an-alasset-url-from-a-phasset
                                // AF3C1B68-222B-43D3-9478-53097429F1B2/L0/001 becomes
                                // assets-library://asset/asset.JPG?id=AF3C1B68-222B-43D3-9478-53097429F1B2&ext=JPG
                                QString theId = QString::fromNSString(asset.localIdentifier);
                                QString theUrl = "assets-library://asset/asset.";
                                theUrl.append(theSuffix).append("?id=");
                                theUrl.append(theId.split('/').first());
                                theUrl.append("&ext=").append(theSuffix);
                                // qDebug() << "URL: " << theUrl;
                    
                                assetsMap.insert(modificationDate, theUrl);
                            } // assets in collection
                    
                            // now we can fill our list of assets-URLs (sorted descendend by modificationDate)
                            QStringList sortedAssetsList;
                            QMapIterator<QDateTime, QString> assetsIterator(assetsMap);
                            assetsIterator.toBack();
                            while (assetsIterator.hasPrevious()) {
                                assetsIterator.previous();
                                sortedAssetsList.append(assetsIterator.value());
                            }
                    
                            // insert sorted list of URLLs into albums map
                            albumsWithSortedAssetsMap.insert(theAlbum, sortedAssetsList);
                    
                        } // media collections in smart album
                        // now we have all albums sorted by album name together with sorted collections of assets, where the newest comes first
                        return albumsWithSortedAssetsMap;
                    }
                    

                    Good to know: if you fetch the assets, then switch to iOS Camera and create new Photos or delete Photos, go back to your App and again call the same method to fetch assets you’ll get the old content. I had to create a new instance of my IosUtil class to be able to get the newest data from Phto Library.

                    ekke ... Qt Champion 2016 | 2024 ... mobile business apps
                    5.15 --> 6.8 https://t1p.de/ekkeChecklist
                    QMake --> CMake https://t1p.de/ekkeCMakeMobileApps

                    1 Reply Last reply
                    5
                    • SGaistS Offline
                      SGaistS Offline
                      SGaist
                      Lifetime Qt Champion
                      wrote on last edited by
                      #9

                      Thank you very much !

                      Interested in AI ? www.idiap.ch
                      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                      ekkescornerE 1 Reply Last reply
                      0
                      • SGaistS SGaist

                        Thank you very much !

                        ekkescornerE Offline
                        ekkescornerE Offline
                        ekkescorner
                        Qt Champions 2016
                        wrote on last edited by
                        #10

                        the code above only fetches smart albums. if you also need albums created manually from user, you must fetch them, too:

                        PHFetchResult *userCollections = [PHCollectionList fetchTopLevelUserCollectionsWithOptions:nil];
                        

                        and if you need sync’d albums:

                        PHFetchResult *syncedAlbums = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumSyncedAlbum options:nil];
                        

                        user collections tested, sync’d collections not tested yet because I don’t need them

                        ekke ... Qt Champion 2016 | 2024 ... mobile business apps
                        5.15 --> 6.8 https://t1p.de/ekkeChecklist
                        QMake --> CMake https://t1p.de/ekkeCMakeMobileApps

                        1 Reply Last reply
                        2

                        • Login

                        • Login or register to search.
                        • First post
                          Last post
                        0
                        • Categories
                        • Recent
                        • Tags
                        • Popular
                        • Users
                        • Groups
                        • Search
                        • Get Qt Extensions
                        • Unsolved