How do I fetch only certain PHCollections? - iphone

I've created three PHCollections within my app. In a different part of my app, I'm attempting to fetch them and display them in a table view. I can get all of the user created libraries by using the following code
let topLevelUserCollections: PHFetchResult = PHCollectionList.fetchTopLevelUserCollectionsWithOptions(nil)
self.collectionsFetchResults = [topLevelUserCollections];
self.collectionsLocalizedTitles = ["My Clips"];
PHPhotoLibrary.sharedPhotoLibrary().registerChangeObserver(self) //With this you need to conform to PHPhotoLibraryChangeObserver
but how can I fetch only the asset collection I want? Also, I only want video and not images, is there a way to fetch only results with videos assests?

You are calling PHCollectionList.fetchTopLevelUserCollectionsWithOptions with a parameter of nil. But that nil is the PHFetchOptions. Those PHFetchOptions are exactly how you make this sort of specification.
In particular, if you created these collections yourself, you have their localIdentifier values. That is exactly what you would specify in the PHFetchOptions predicate to pull out those collections. You could also do it by localizedTitle and so on.

Related

Delete specific value from firebase database using swift

Firebase Database
I tried using this bit of code but it doesn't seem to work. I take the name the user selects and store it in nameList.
Lets say I store Blake Wodruff in nameList[0].
How do I remove only that name?
var nameList = [String](repeating: "", count:100)
func remove() {
print(nameList[countAddNames])
let usernameRef = Database.database().reference().child("Candidate 1").child("alton").child(nameList[countAddNames]);
usernameRef.removeValue();
}
To write to or delete a node, you must specify its entire path. So to delete node 0 from your JSON, you'd do:
let usernameRef = Database.database().reference().child("Candidate 1").child("alton").child("0");
usernameRef.removeValue();
Or a bit shorter:
let usernameRef = Database.database().reference().child("Candidate 1/alton/0");
usernameRef.removeValue();
If you only know the name of the user you want to remove, you'll need to first look up its index/full path before you can remove it. If you have the data in your application already, you can do it in that code. Otherwise you may have to use a database query (specifically .queryOrderedByValue and .queryEqualToValue) to determine where the value exists in the database.
Also see: Delete a specific child node in Firebase swift
Once you remove a value from your JSON structure, Firebase may no longer recognize it as an array. For this reason it is highly recommended to not use arrays for the structure that you have. In fact, I'd model your data as a set, which in JSON would look like:
"alton": {
"Jake Jugg": true,
"Blake Wodruff": true,
"Alissa Sanchez": true
}
This would automatically:
Prevent duplicates, as each name can by definition only appear once.
Make removing a candidate by their name as easy as Database.database().reference().child("Candidate 1/alton/Jake Jugg").removeValue()
For more on this, also see my answer to Firebase query if child of child contains a value

Retrieving Finder tags from within a Swift or Objective-C app

Using NSURL APIs, how can a I determine which tags are set on a directory? The only API I'm aware of does indeed return a number associated with tags, but I'm not sure how to extract the specific tags from the returned value.
For example this will return 4 for directory B. I need to determine that both Blue and Green tags are set.
let url = URL(fileURLWithPath: "/Users/Username/Desktop/Test/B")
let resourceValues = try! url.resourceValues(forKeys:
[URLResourceKey.labelNumberKey])
print(resourceValues.labelNumber!) // 4
I've seen some use an enum to map the results back to Swift, but this doesn't seem to handle multiple tags.
enum LabelColor: Int {
case none
case gray
case green
case purple
case blue
case yellow
case red
case orange
}
So it seems an OptionSet would be the best implementation here for Swift.
If someone can point me to the algorithm used to extract tags from the total number that would be great!
I'm not aware of any way to grab the numeric values to the tags other than through a shell.
However, you can, as #Martin-R suggested, get an array of the tags attached to the file. I think this is best because user's can create custom tags, which may be hard to identify numerically.
I would suggest getting the array by using ⤵︎
var itemTags: [String] = []
do {
let resources = try url.resourceValues(forKeys: [.tagNamesKey])
if let tags = resources.tagNames {
itemTags = tags // ["Green", "Red"]
}
} catch {}
Once you have the array then you can just use some kind of enum & switch, for loop, or if/else to match it to colours you designate yourself.
Secret Sauce ⤵︎
Now the problem is that if you're sandboxed and you try this you'll probably only get one tag I imagine. It'll be the front-most tag.
This is just another one of Apple's security measures. To get around this your sandbox needs to extend to this resource.
It's a bit much to get into security scopes in this post, but here are two things you could try.
Use NSOpenPanel() to get the url or parent directory url. This will automatically give you privileges to that resource for that session. You can bookmark it, resolve it, and start accessing it.
Stop using the sandbox
Unfortunately, I don't know of other solutions that would work. I chose the first and it's the least painful at the moment.

How to use Dynamic Multiple NSPredicate from NSArray in Core data

I am fairly new to core data. I have database which contains articles with different categories. I want to fetch data from multiple categories, which can be selected by user on the fly. Now I have NSArray which contains selected multiple categories (count from 1 to n) I want to add predicate for selected categories but I'm not able to do so. as per my knowledge i have added for loop for adding categories in predicate but it is not working.
for i in 0...(catArray?.count)!-1 {
let str = String(format:"catId = %#",(catArray?.object(at: i) as? NSNumber)!)
predicateString = predicateString+str
}
let dP = NSPredicate(format:"%#",predicateString)
fetchedRequest.predicate=dP;
but app is crashing while fetching request.
Is there any other way to do it?
Please help me with this.
Any help is much appreciated.
To select objects which have any category from the given array
a simple predicate is sufficient:
NSPredicate(format: "catId IN %#", catArray)
Remark: Never use String(format:) to build predicates dynamically,
because almost surely the quoting and escaping will be wrong.
Use only NSPredicate(format:) and, if necessary, NSCompoundPredicate.

Insert initial items to Core Data in Swift

I'm new to Swift developing. I made tableView with 16 rows - there are names and prices of every items.
When the user clicks on a row, a new tableView (with static cell) is shown. The user can edit price (I only need price to be mutable) and save it. Then, the original tableView with the new price is shown.
BUT when I stop and load app again there is the original prices.
I found out that I have to use Core Data to storage data permanently. BUT I need the database to be filled with these 16 rows (with the first load after installing) and then let user to change price permanently (or until change it again).
It is possible? And how? Should I use Core Data or is there an easier option?
Pretty much everything suggested to you so far is more complex than it needs to be. You're talking about local data, and a very small amount of it.
The simplest option is to use a plist.
Xcode can help if you create a new file, select Resource as the type and then Property List. Once created it'll contain a dictionary by default, but you can convert that to an array. Add your data, so you have an array of dictionaries with your values for price etc.
Now, this file will be part of the bundle when you run the app, so you can't edit it. You should copy the file by finding it with NSBundle and copying it with NSFileManager into the documents folder.
Once it's there you can use NSArray init?(contentsOfFile path: String) to load the data. Use mutableCopy to create a version you can edit. You can use this array to drive your table view and you can edit the values it contains. Note that with this simple technique the dictionaries in the array will be immutable, so you're probably better off using NSPropertyListSerialization class func propertyListWithData(_ data: NSData, options opt: NSPropertyListReadOptions, format format: UnsafeMutablePointer<NSPropertyListFormat>) throws -> AnyObject with an option of MutableContainersAndLeaves instead.
Once you've edited the array contents you can write it back to disk for next run (with class func dataWithPropertyList(_ plist: AnyObject, format format: NSPropertyListFormat, options opt: NSPropertyListWriteOptions) throws -> NSData)

Permanenly saving a Int in SpriteKit

I'm trying to create a game and need to be able to save a number and retrieve it. I've found another tutorial on this but it is outdated and kept giving errors:
//To save highest score
var highestScore:Int = 20
NSUserDefaults.standardUserDefaults().setObject(highestScore,
forKey:"HighestScore")
NSUserDefaults.standardUserDefaults().synchronize()
//To get the saved score
var savedScore: Int =
NSUserDefaults.standardUserDefaults().objectForKey("HighestScore") as Int
println(savedScore)
More Details: It's to save a highscore if that helps (which I don't think it does).
Any help is welcome, Thanks.
NSUserDefaults.standardUserDefaults().setInteger(20, forKey: "HighestScore")
let valueOrZeroIfNotSet = NSUserDefaults.standardUserDefaults().integerForKey("HighestScore")
NSUserdefaults are a really useful tool, you can permenantly create mutable variables that can be read and written anywhere and anytime. Heres a brief explanation of how to use them.
let saves = NSUserdefaults.standardUserDefaults()
You need to declare a NSUserdefaults to begin, now this is where you will be storing data. Imagine it as a Bookshelf, right now its empty but you can fill it with all forms of information.
Now that we have our 'Bookshelf', we can start filling it with Books, these books can be everything such as Integers, and Strings.
If we want to store my name (Peter) in a 'book' on the shelf, we would first have to create the book and give it a name. The name of the book is called the "key". The key has to be a unique String. Because Im storing my name the key will be "myName". Now we know our key to write to, now lets fill the book with information (Which is my name).
saves.setString("Peter", forKey: "myName")
Now we've made a book in our bookshelf that stores our name.
We will probably want to read this information just in case we need it! We can access books from our bookshelf easily with:
saves.stringForKey("myName")
Now we did need the key (the books name) so we could find the right book of information.
Thats pretty much it for NSUserdefaults for you.