I am trying to use the includeAllBurstAssets of PHFetchOptions.
In my camera roll, there are about 5 burst assets (each with about 10 photos).
To enumerate the assets in the Camera Roll I'm doing the following:
PHFetchOptions *fetchOptions = [PHFetchOptions new];
fetchOptions.includeAllBurstAssets = YES;
PHFetchResult *fetchResult = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeSmartAlbumUserLibrary options:fetchOptions];
PHFetchResult *assetFetch = [PHAsset fetchAssetsInAssetCollection:fetchResult[0] options:fetchOptions];
NSLog(#"Found assets %lu",(unsigned long)assetFetch.count);
No matter, if I set the includeAllBurstAssets property to NO or YES, I get the exact same count of assets.
I expected the number to be higher, if includeAllBurstAssets is set to YES.
Is this a bug or I am interpreting the includeAllBurstAssets in a wrong way.
There is a special method to query for all images of a burst sequence.
[PHAsset fetchAssetsWithBurstIdentifier:options:]
In your case you need to iterate over your assetFetch object and check if the PHAsset represents a burst.
PHAsset defines the property BOOL representsBurst
If that returns YES, fetch all assets for that burst sequence.
Here is a code snippet that might help to understand:
if (asset.representsBurst) {
PHFetchOptions *fetchOptions = [PHFetchOptions new];
fetchOptions.includeAllBurstAssets = YES;
PHFetchResult *burstSequence = [PHAsset fetchAssetsWithBurstIdentifier:asset.burstIdentifier options:fetchOptions];
PHAsset *preferredAsset = nil;
for (PHAsset *asset_ in burstSequence) {
if (PHAssetBurstSelectionTypeUserPick == asset.burstSelectionTypes || PHAssetBurstSelectionTypeAutoPick == asset.burstSelectionTypes) {
asset = preferredAsset = asset_;
}
}
if (!preferredAsset) {
asset = burstSequence.firstObject;
}
}
As you can see, the burstSelectionTypes are not always set resp. are sometimes PHAssetBurstSelectionTypeNone for all assets of a burst sequence.
Related
I would like to know how to loop the following animation of a button in Kotlin:
Example: https://ibb.co/XD7H073
As you can see in the image my goal is to constantly move the button up and down.
Here are the core parts of the code I´m trying to write:
ObjectAnimator.ofFloat(button, "translationY", 30f).apply {
duration = 500
start()
}
ObjectAnimator.ofFloat(button, "translationY", -30f).apply {
duration = 500
start()
}
Thanks to the one who can show me how to put these two animations in an array and then loop the array infinitely!
//////////////////
Solution:
val animations = arrayOf(-140f).map { translation ->
ObjectAnimator.ofFloat(button, "translationX", translation).apply {
duration = 800
repeatCount = ObjectAnimator.INFINITE
repeatMode = ObjectAnimator.RESTART
}
}
Not tested, you may need to play with ObjectAnimator.REVERSE/RESTART and/or add from value in ObjectAnimator.ofFloat(_, _, from, to)
val animations = arrayOf(30f, -30f).map { translation ->
ObjectAnimator.ofFloat(button, "translationY", translation).apply {
duration = 500
repeatCount = ObjectAnimator.INFINITE
repeatMode = ObjectAnimator.REVERSE
}
}
val set = AnimatorSet()
set.playTogether(animations)
set.start()
NOTE: See amended post below re: Hardware mirroring
I have written two Swift functions that toggle the display mirroring in OSX. Both work; the difference between them is just syntax when dealing with pointers. For the convenience of those interested in learning how to toggle mirroring in Swift, I have included the text of the playground file below.
My question is about memory allocation. Here is the section of interest:
toggleMirroringUgly
// allocate space for array
let displayListPtr = displayIDListPtr.alloc(Int(displayCount)) //see typealias above
// fill the list
postError(CGGetActiveDisplayList(displayCount, displayListPtr, &activeCount))
toggleMirroring
// allocate space for list of displays
var displayIDList = Array<CGDirectDisplayID>(count: Int(displayCount), repeatedValue: kCGNullDirectDisplay)
// fill the list
postError(CGGetActiveDisplayList(displayCount, &displayIDList, &activeCount))
CGGetActiveDisplayList is a low-level function call that relies on data being arranged in consecutive memory locations. I am reasonably confident that “alloc” from the ugly version is contiguous. Empirically, it seems that the “Array(…)” call is also contiguous, but can I rely on that always being true (e.g., if the number of displays grows)? Is this assumption about the Swift array initializer poor form?
Here’s all the code; apologies for formatting issues. Note that only one of the two functions should be called; otherwise, you’ll end up where you started.
//: Playground - noun: a place where people can play
import Cocoa
// apparently not defined in Swift version of SDK 10.11 (XCode 7.3.1), so add manually
let kCGNullDirectDisplay = CGDirectDisplayID(0)
let kCGDirectMainDisplay = CGMainDisplayID() // not used here, just for the record
let maxDisplays:UInt32 = 20 // not used
var onlineCount:UInt32 = 0 // not used
func postError(error : CGError){
if error != CGError.Success {
print("got an error")
}
}
// this toggles all active displays, online or not
func toggleMirroring(){
var displayCount:UInt32 = 0
var activeCount:UInt32 = 0
//var onlineCount:UInt32 = 0 //not used
//get count of active displays (by passing nil to CGGetActiveDisplayList
postError(CGGetActiveDisplayList(0, nil, &displayCount))
if displayCount < 2 { return } // no point in any mirroring functions
//***
// allocate space for list of displays
var displayIDList = Array<CGDirectDisplayID>(count: Int(displayCount), repeatedValue: kCGNullDirectDisplay)
// fill the list
postError(CGGetActiveDisplayList(displayCount, &displayIDList, &activeCount))
//***
// determine if mirroring is active
// hack to convert from boolean_t (aka UInt32) to swift's bool
let displaysMirrored = CGDisplayIsInMirrorSet(CGMainDisplayID()) != 0
// set master based on current mirroring state
// if mirroring, master = null, if not, master = main display
let master = (true == displaysMirrored) ? kCGNullDirectDisplay : CGMainDisplayID()
// start the configuration
var configRef:CGDisplayConfigRef = nil //swift 3 syntax
postError(CGBeginDisplayConfiguration(&configRef));
for i in 0..<Int(displayCount) {
let currentDisplay = CGDirectDisplayID(displayIDList[i])
if CGMainDisplayID() != currentDisplay {
CGConfigureDisplayMirrorOfDisplay(configRef, currentDisplay, master);
}
}
if (false){ // change to true in order to execute the toggle
postError(CGCompleteDisplayConfiguration (configRef,CGConfigureOption.Permanently))
}
// The first entry in the list of active displays is the main display. In case of mirroring, the first entry is the largest drawable display or, if all are the same size, the display with the greatest pixel depth.
// The "Permanently" option might not survive reboot when run from playground, but does when run in an application
}
func toggleMirroringUgly(){
// just to decrease eye strain
typealias displayIDListPtr = UnsafeMutablePointer<CGDirectDisplayID>
typealias configurationRefPtr = UnsafeMutablePointer<CGDisplayConfigRef>
//get count of active displays (by passing nil to CGGetActiveDisplayList
postError(CGGetActiveDisplayList(0, nil, &displayCount))
if displayCount < 2 { return } // no point in any mirroring functions
// ***
// allocate space for array
let displayListPtr = displayIDListPtr.alloc(Int(displayCount)) //see typealias above
// fill the list
postError(CGGetActiveDisplayList(displayCount, displayListPtr, &activeCount))
// ***
// determine if mirroring is active
// hack to convert from boolean_t (aka UInt32) to swift's bool
let displaysMirrored = CGDisplayIsInMirrorSet(CGMainDisplayID()) != 0
// set master based on current mirroring state
// if mirroring master = null, if not, master = main display
let master = (true == displaysMirrored) ? kCGNullDirectDisplay : CGMainDisplayID()
// make room for the configuration reference
let configRefPtr = configurationRefPtr.alloc(1) //see typealias above
// start the configuration
postError(CGBeginDisplayConfiguration (configRefPtr));
for i in 0..<displayCount {
let currentDisplay = CGDirectDisplayID(displayListPtr[Int(i)])
if CGMainDisplayID() != currentDisplay {
CGConfigureDisplayMirrorOfDisplay(configRefPtr[0], currentDisplay, master);
}
}
if (false){ //change to true in order to flip the mirroring
// make it happen
postError(CGCompleteDisplayConfiguration (configRefPtr[0],CGConfigureOption.Permanently));
}
// The first entry in the list of active displays is the main display. In case of mirroring, the first entry is the largest drawable display or, if all are the same size, the display with the greatest pixel depth.
// The "Permanently" option might not survive reboot when run from playground, but does when run in an application
}
toggleMirroring()
Arrays don't necessarily use contiguous storage. There is a ContiguousArray type which you can use if you are so inclined, but you'll still need to deal with the possible difference between your maximum size and the actual size returned after the final call to CGGetActiveDisplayList.
One way of cleaning this up might be to make a custom convenience initializer for Array:
extension Array {
init<Size: IntegerType>(
fillingBufferOfSize maxSize: Size,
#noescape fillBuffer: (buffer: UnsafeMutablePointer<Element>, count: inout Size) throws -> ()) rethrows
{
let maxSizeAsInt = Int(maxSize.toIntMax())
let buf = UnsafeMutablePointer<Element>.alloc(maxSizeAsInt)
defer { buf.dealloc(maxSizeAsInt) }
var actualCount: Size = 0
try fillBuffer(buffer: buf, count: &actualCount)
self.init(UnsafeBufferPointer(start: buf, count: Int(actualCount.toIntMax())))
}
}
Then you can use Array(fillingBufferOfSize: ...):
var maxActive: UInt32 = 0
CGGetActiveDisplayList(0, nil, &maxActive)
let displays = Array(fillingBufferOfSize: maxActive) { (buffer, count) in
CGGetActiveDisplayList(maxActive, buffer, &count)
}
I upgraded my computer with a new video card and NVIDIA drivers and discovered my code above no longer works fully - turns mirroring on but not off. Apparently, there's an option for drivers to use hardware or software mirroring, and that changes the coding. I post below a revised version.
It has only been tested on my system (10.12.2) and card (GTX 980Ti), but I think the logic should accommodate software mirroring and fairly recent OS versions as well. If you have more than 2 displays, you can probably modify it, with heroic effort, to mirror arbitrary combinations. My code will just mirror whatever is considered the main display (or the lowest rez one, in software mirroring) on all the others.
Although jbandes' note re: ContiguousArray was informative, it does not work in this case - see the comments in the code. This code assumes that the allocated array of UInt32s will be contiguous. (Too much work to get fancy with malloc and casting, but this is not production ready.)
Good luck to the 2 people who might be interested!
//: Playground - noun: a place where people can play
import Cocoa
import Foundation
func postError(_ error : CGError){
if error != CGError.success {
print("got an error")
}
}
func disableHardwareMirroring(){
// designed for hardware mirroring with > 1 display
// should be no penalty for running with only 1 display, using either hardware or software mirroring drivers
// but not tested
// start the configuration
var configRef:CGDisplayConfigRef? = nil
postError(CGBeginDisplayConfiguration(&configRef))
// only interested in the main display
// kCGNullDirectDisplay parameter disables hardware mirroring
CGConfigureDisplayMirrorOfDisplay(configRef, CGMainDisplayID(), kCGNullDirectDisplay)
// may not be permanent between boots using Playgroud, but is in an application
postError(CGCompleteDisplayConfiguration (configRef,CGConfigureOption.permanently))
}
func toggleMirroring(){
var displayCount:UInt32 = 0
var activeCount:UInt32 = 0 //used as a parameter, but value is ignored
//var onlineCount:UInt32 = 0 //not used
//get count of active displays (by passing nil to CGGetActiveDisplayList
postError(CGGetActiveDisplayList(0, nil, &displayCount))
if displayCount == 1 {
// either it's hardware mirroring or who cares?
disableHardwareMirroring()
return
}
// allocate space for list of displays
// tried to use ContiguousArray, but CGGetActiveDisplayList requires Array<CGDirectDisplayID> parameter
// ContiguousArrays cannot be typecast to Arrays (at least not easily)
var displayIDList = Array<CGDirectDisplayID>(repeating: kCGNullDirectDisplay, count: Int(displayCount))
// fill the list
postError(CGGetActiveDisplayList(displayCount, &(displayIDList), &activeCount))
// determine if mirroring is active (only relevant for software mirroring)
// hack to convert from boolean_t (aka UInt32) to swift's bool
let displaysMirrored = CGDisplayIsInMirrorSet(CGMainDisplayID()) != 0
// set master based on current mirroring state
// if mirroring, master = null, if not, master = main display
let master = (true == displaysMirrored) ? kCGNullDirectDisplay : CGMainDisplayID()
// start the configuration
var configRef:CGDisplayConfigRef? = nil
postError(CGBeginDisplayConfiguration(&configRef))
for i in 0..<Int(displayCount) {
let currentDisplay = CGDirectDisplayID(displayIDList[i])
if CGMainDisplayID() != currentDisplay {
CGConfigureDisplayMirrorOfDisplay(configRef, currentDisplay, master)
}
}
postError(CGCompleteDisplayConfiguration (configRef,CGConfigureOption.permanently))
// The first entry in the list of active displays is the main display. In case of mirroring, the first entry is the largest drawable display or, if all are the same size, the display with the greatest pixel depth.
// The "Permanently" option might not survive reboot when run from playground, but does when run in an application
}
if (false) { // change to true to run the code, false to edit
toggleMirroring()
}
I am trying to write a program that will recognize an image on the screen, compare it against a resource library, and then calculate based on the result of the image source.
The first thing that I did was to create the capture screen function which looks like this:
private Bitmap Screenshot()
{
System.Drawing.Bitmap Table = new System.Drawing.Bitmap(88, 40, PixelFormat.Format32bppArgb);
System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(RouletteTable);
g.CopyFromScreen(1047, 44, 0, 0, Screen.PrimaryScreen.Bounds.Size);
return Table;
}
Then, I analyze this picture. The first method I used was to create two for loops and analyze both the bitmaps pixel by pixel. The problem with this method was time, it took a long time to complete 37 times. I looked around and found the convert to bytes and the convert to hash methods. This is the result:
public enum CompareResult
{
ciCompareOk,
ciPixelMismatch,
ciSizeMismatch
};
public CompareResult Compare(Bitmap bmp1, Bitmap bmp2)
{
CompareResult cr = CompareResult.ciCompareOk;
//Test to see if we have the same size of image
if (bmp1.Size != bmp2.Size)
{
cr = CompareResult.ciSizeMismatch;
}
else
{
//Convert each image to a byte array
System.Drawing.ImageConverter ic = new System.Drawing.ImageConverter();
byte[] btImage1 = new byte[1];
btImage1 = (byte[])ic.ConvertTo(bmp1, btImage1.GetType());
byte[] btImage2 = new byte[1];
btImage2 = (byte[])ic.ConvertTo(bmp2, btImage2.GetType());
//Compute a hash for each image
SHA256Managed shaM = new SHA256Managed();
byte[] hash1 = shaM.ComputeHash(btImage1);
byte[] hash2 = shaM.ComputeHash(btImage2);
for (int i = 0; i < hash1.Length && i < hash2.Length&& cr == CompareResult.ciCompareOk; i++)
{
if (hash1[i] != hash2[i])
cr = CompareResult.ciPixelMismatch;
}
}
return cr;
}
After I analyze the two bitmaps in this function, I call it in my main form with the following:
Bitmap Table = Screenshot();
CompareResult success0 = Compare(Properties.Resources.Result0, Table);
if (success0 == CompareResult.ciCompareOk)
{ double result = 0; Num.Text = result.ToString(); goto end; }
The problem I am getting is that once this has all been accomplished, I am always getting a cr value of ciPixelMismatch. I cannot get the images to match, even though the images are identical.
To give you a bit more background on the two bitmaps, they are approximately 88 by 40 pixels, and located at 1047, 44 on the screen. I wrote a part of the program to automatically take a picture of that area so I did not have to worry about the wrong location or size being captured:
Table.Save("table.bmp");
After I took the picture and saved it, I moved it from the bin folder in the project directly to the resource folder and ran the program again. Despite all of this, the result is still ciPixelMismatch. I believe the problem lies within the format that the pictures are being saved as. I believe that despite them being the same image, they are being analyzed in different formats, maybe one of the pictures contains a bit more information than the other which is causing the mismatch. Can somebody please help me solve this problem? I am just beginning with my c# programming, I am 5 days into the learning process, and I am really at a loss for this.
Yours sincerely,
Samuel
I am trying to search through the contents of my attributed UITextView with the following code:
NSRange range = NSMakeRange(0, haystack.length);
range = [haystack rangeOfString:searchText options:NSCaseInsensitiveSearch range:range];
while (range.location != NSNotFound)
{
[_attrString addAttribute:NSBackgroundColorAttributeName value:[UIColor yellowColor] range:NSMakeRange(range.location, range.length)];
range = NSMakeRange(range.location+range.length, haystack.length-(range.location+range.length));
range = [haystack rangeOfString:searchText options:NSCaseInsensitiveSearch range:range locale:nil];
}
...
_textView.attributedText = _attrString;
_attrString is of course a NSMutableAttributedString
This works fine except it is very slow with large texts. With a UITextView containing 156,000 characters it takes a couple of seconds for the changes to become visible. If I NSLog the single steps of the loop I can see that the code executes fast. It takes a couple of seconds for the changes to become visible in the UITextView.
Does it just take a while for the attributed UITextview to redraw? Is do anything to speed up the process? I tried searching through the text with regular expressions, but that didn't seem to change anything.
Thanks
Use NSPredicate
UITextField *txtFld=(UITextField *)sender;
// if (![txtFld.text isEqualToString:#""]) {
//[self getSearchResult:txtFld.text];
// }else{
// [self makeViewSmall];
// }
// For string kind of values:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF contains[cd] %#", txtFld.text];
NSArray *results = [[sortedDic valueForKey:#"locations"] filteredArrayUsingPredicate:predicate];
NSLog(#"Result=%#",results);*/
I have an array which is filled with platforms that are supposed to move.
var MovingPlatformArray:Array = new Array();
for (var c:int = numChildren - 1; c >= 0; c--){
var child3:DisplayObject = getChildAt(c);
if (child3.name == "movingplatform"){
MovingPlatformArray.push(child3);
}
}
this.addEventListener(Event.ENTER_FRAME,ctrl_birdie);
function ctrl_birdie(e:Event):void{
for(var c in MovingPlatformArray){
MovingPlatform[c].y += speed;
if(MovingPlatformArray[c].hitTestPoint(birdie.x,birdie.y,true)){
birdtelleryvertrager=0;
birdtellery = 0;
birdie.y-=14;
}
if(movingplatform.y <= 25){
speed = 2;
}
if(movingplatform.y >= 350){
speed = -2;
}
}
Right now I have 2 moving platforms in this array. But only one moves up and down. But they both register a touch with the birdie. Am I doing something wrong?
In your listener, you're only setting the position of one platform, which ever one "movingplatform" is a reference to. As all your stage instances of moving platforms are named "movingplatform", one lucky platform is getting referenced by name (the rest ignored), instead of what you intended, which is to use the references in your array and adjust each platform.
You probably meant for movingplatform to be a local variable in your event handler, declared something like this:
var movingplatform:DisplayObject = MovingPlatformArray[c] as DisplayObject;
I'd recommend using a for each loop in place of the for in, because I think it's a little cleaner, but this is a minor style thing:
for each (var platform:DisplayObject in MovingPlatformArray)
{
platform.y += speed;
... rest of your code ...
}
For the sake of clarity, I edited the loop variable to be platform instead of movingplatform, to avoid confusion of having a local variable shadow a stage instance (i.e. this.movingplatform). I wanted it to be clear that the stage instance name is not being used here, because the unintentional instance name reference in your code is the source of your problem in the first place.
As far as i'm concerned, you have two options. use a for each, as adam smith suggested or use a for-loop as it was intended to be used :)
for(var c:uint = 0; c < MovingPlatformArray.length; c++){...
and btw: should "MovingPlatform[c].y += speed;" not be "MovingPlatformArray[c].y += speed;"?
edit: looking at your code, i would also suggest you use MovingPlatformArray[c].hitTestObject(birdie) instead of MovingPlatformArray[c].hitTestPoint(birdie.x,birdie.y,true)
If I were you, I would bring the logic for the platform out, and store it in a class. (Ideally you would do this for the birdie object as well). I have created an example below. The movieclips on the stage should extend Platform rather than MovieClip so they invoke the methods at the bottom.
// Use vectors if you know all the items are going to be the same type
var platforms:Vector.<Platform> = new <Platform>[];
for (var c:int = numChildren - 1; c >= 0; c--){
var child:DisplayObject = getChildAt(c);
// You shouldn't check against names (as per the original post). Because
// names should be unique
if (child is Platform){
platforms.push(child);
// This could be random so each platform has a different range
// This means platform 1 could go from y 30 to y 400, platform 2
// could go from y 60 to y 200, etc
child.setRange(25, 400);
}
}
this.addEventListener(Event.ENTER_FRAME, gameLoop);
// Have an overall game loop
function gameLoop(e:Event):void {
// Loop over the platforms
platforms.forEach(function(item:Platform, i:int, a:Vector.<Platform>):void {
// Hit test function in the class means you only have to pass in one mc
// rather than the points and a boolean
if(item.hitTest(birdie)) {
birdtelleryvertrager=0;
birdtellery = 0;
birdie.y-=14;
}
// Removed the movement logic, this should be kept out of the game loop
// plus how much better does this read?
item.move();
});
}
Then in a class location somewhere, like in a folder game/activeObjects
// A class for the platform stored else where
package game.activeObjects
{
import flash.display.MovieClip;
/**
*
*/
public class Platform extends MovieClip {
private const SPEED:Number = 2;
private var _direction:int = 1;
private var _minimumHeight:Number = 25;
private var _maximumHeight:Number = 350;
public function Platform() {
}
public function setRange(minimumHeight:Number, maximumHeight:Number) {
_minimumHeight = minimumHeight;
_maximumHeight = maximumHeight;
}
public function move():void {
this.y += SPEED * _direction;
if(this.y <= _minimumHeight) {
_direction = 1;
} else if(this.y >= _maximumHeight) {
_direction = -1;
}
}
public function hitTest(mc:MovieClip):Boolean {
return hitTestPoint(mc.x,mc.y,true);
}
}
}