DynamicProperty vs MutableProperty vs AnyProperty vs ConstantsProperty - ios

What's difference between them? Could you give me an example of in which scenario I should use dynamic/mutable/any/constants property?

All your answer are in this link Property.swift
I give you some examples:
let privatString = MutableProperty<String>("PrivatString")
// AnyProperty are only for observing. You can't change it with observableProperty.value
let observableProperty: AnyProperty = AnyProperty<String>(privatString)
print(observableProperty)
// ConstantProperty describes observable constant value.
let constantProperty = ConstantProperty<String>("ConstantString")
// constantProperty.value = "" Error
// Thread safe observable mutable property. It's value is changable
let mutableProperty = MutableProperty<String>("mutableProperty")
mutableProperty.value = "New mutable property value"
// DynamicProperty uses KVO.
let dynamicProperty = DynamicProperty(object: self.view.layer, keyPath: "bounds")
dynamicProperty.producer.startWithNext { frame in
let frame = frame as! NSValue
let rect = frame.CGRectValue()
print(rect)
}

Related

Developing an ARKit app that leaves text for others to view

I am creating an iOS AR app that sets text in a specific location and leaves it there for others to view. Is there a better way to implement it than what I am doing?
Currently, I have it set so that the text is saved to Firebase and loads it by setting the nodes relative to the camera’s position. I’m wondering if there is a way to save ARAnchors in a fashion similar to what I am doing but is that possible?
My current function for saving the text to the location via a user tapping the screen:
/*
* Variables for saving the user touch
*/
var touchX : Float = 0.0
var touchY : Float = 0.0
var touchZ : Float = 0.0
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
// will be used for getting the text
let textNode = SCNNode()
var writing = SCNText()
// gets the user’s touch upon tapping the screen
guard let touch = touches.first else {return}
let result = sceneView.hitTest(touch.location(in: sceneView), types: [ARHitTestResult.ResultType.featurePoint])
guard let hitResult = result.last else {return}
let hitTransform = SCNMatrix4.init(hitResult.worldTransform)
let hitVector = SCNVector3Make(hitTransform.m41, hitTransform.m42, hitTransform.m43)
// saves X, Y, and Z coordinates of touch relative to the camera
touchX = hitTransform.m41
touchY = hitTransform.m42
touchZ = hitTransform.m43
// Was thinking of adding the ability to change colors. Probably can skip next seven lines
var colorArray = [UIColor]()
colorArray.append(UIColor.red)
writing = SCNText(string: input.text, extrusionDepth: 1)
material.diffuse.contents = colorArray[0]
writing.materials = [material]
// modifies the node’s position and size
textNode.scale = SCNVector3(0.01, 0.01, 0.01)
textNode.geometry = writing
textNode.position = hitVector
sceneView.scene.rootNode.addChildNode(textNode)
// last few lines save the info to Firebase
let values = ["X" : touchX, "Y" : touchY, "Z" : touchZ, "Text" : input.text!] as [String : Any]
let childKey = reference.child("Test").childByAutoId().key
if input.text != nil && input.text != "" {
let child = reference.child("Test").child(childKey!)
child.updateChildValues(values)
} else {
let child = reference.child("Test").child(childKey!)
child.updateChildValues(values)
} // if
} // override func
/*
* Similar to the previous function but used in next function
*/
func placeNode(x: Float, y: Float, z: Float, text: String) -> Void {
let textNode = SCNNode()
var writing = SCNText()
let hitVector = SCNVector3Make(x, y, z)
touchX = x
touchY = y
touchZ = z
var colorArray = [UIColor]()
colorArray.append(UIColor.red)
writing = SCNText(string: text, extrusionDepth: 1)
material.diffuse.contents = colorArray[0]
writing.materials = [material]
textNode.scale = SCNVector3(0.01, 0.01, 0.01)
textNode.geometry = writing
textNode.position = hitVector
sceneView.scene.rootNode.addChildNode(textNode)
} // func
/*
* This next function is used in my viewDidLoad to load the data
*/
func handleData() {
reference.child("Test").observeSingleEvent(of: .value, with: { (snapshot) in
if let result = snapshot.children.allObjects as? [DataSnapshot] {
for child in result {
let xCoord = Float(truncating: child.childSnapshot(forPath: "X").value as! NSNumber)
let yCoord = Float(truncating: child.childSnapshot(forPath: "Y").value as! NSNumber)
let zCoord = Float(truncating: child.childSnapshot(forPath: "Z").value as! NSNumber)
let inscription = child.childSnapshot(forPath: "Text").value
self.placeNode(x: xCoord , y: yCoord , z: zCoord , text: inscription as! String)
} // for
} // if
}) // reference
} // func
I have looked into a few things such as ARCore but that looks like it uses Objective-C. I’ve made this app in Swift and I am not sure if I can incorporate ARCore with how I have implemented my current application.
Do I just need to get over it and learn Objective-C? Can I still work with what I have?
I think that ARCore anchors are only available for 24 hours, so that could be a problem.
You probably need to use ARKit2.0's ARWorldMap and save it as data on firebase for others to see the text in the same place, otherwise you are assuming in your code that future users will start their AR session in the exact same position and direction as the person who left the text. You probably need to use core location first to see where in the world the user is.

Type of expression is ambiguous | SpringyCollectionViewFlowLayout

As described in this UICollectionViewFlowlayout, Step 1:
// Need to overflow our actual visible rect slightly to avoid flickering.
var visibleRect = CGRectInset(self.collectionView!.bounds, -100, -100)
var itemsInVisibleRectArray: NSArray = super.layoutAttributesForElementsInRect(visibleRect)!
var itemsIndexPathsInVisibleRectSet: NSSet = NSSet(array: itemsInVisibleRectArray.valueForKey("indexPath") as [AnyObject])
// Step 1: Remove any behaviours that are no longer visible.
var noLongerVisibleBehaviours = (self.dynamicAnimator.behaviors as NSArray).filteredArrayUsingPredicate(NSPredicate(block: {behaviour, bindings in
var currentlyVisible: Bool = itemsIndexPathsInVisibleRectSet.member((behaviour as UIAttachmentBehavior).items.first!.indexPath) != nil
return !currentlyVisible
}))
"Type of expression is ambiguous without more context" .. what should I do? I am really stuck :/
Thank you for any help I can get on this...
If anyone might just want to solve this problem, look here:
let visibleRect = CGRectInset(self.collectionView!.bounds, -100, -100)
let itemsInVisibleRect = super.layoutAttributesForElementsInRect(visibleRect)!
let indexPathsInVisibleRect = Set(itemsInVisibleRect.map({ (attribute) -> NSIndexPath in
return attribute.indexPath
}))
// Step 1: Remove any behaviours that are no longer visible.
let noLongerVisisbleBehaviors = self.dynamicAnimator.behaviors.filter { (eachBehavior) -> Bool in
var currentlyVisible = false
if let behavior = eachBehavior as? UIAttachmentBehavior, first = behavior.items.first as? UICollectionViewLayoutAttributes {
currentlyVisible = indexPathsInVisibleRect.contains(first.indexPath)
}
return !currentlyVisible
}
Thankfully, this has proven to be a truly a huge save for the day :}

Choose UIlabel background Color from Array and then remove it from array. (swift)

I have 3 UiLabels onscreen. I have an array with colors e.g. red,green,blue. I want to set the background of each UiLabel to a a color in the array and then delete the Color from the array so no 2 UiLabels have the same Color.
I was trying to do something like this. it selects a random string in the array but then i cannot assign it to the uilabel because its not of type UIColor.
override func viewDidLoad() {
super.viewDidLoad()
let Colorarray = ["UIColor.redColor()", "UIColor.greenColor()", "UIColor.blueColor()"]
let randomIndex = Int(arc4random_uniform(UInt32(Colorarray.count)))
print(randomIndex)
self.left.text = (Colorarray[randomIndex])
self.left.backgroundColor = (Colorarray[randomIndex])
self.middle.backgroundColor = (Colorarray[randomIndex])
self.right.backgroundColor = (Colorarray[randomIndex])
}
this was the second code i tried
var colorArray = [(UIColor.redColor(), "Red"), (UIColor.greenColor(), "Green"), (UIColor.blueColor(), "Blue")]
//random color
let randomIndex = Int(arc4random_uniform(UInt32(colorArray.count)))
//accessing color
var (color, name) = colorArray[randomIndex]
self.left.text = name
self.left.backgroundColor = color
let leftColorRemoval = (colorArray.removeAtIndex(randomIndex))
print(leftColorRemoval)
var (mcolor, mname) = colorArray[randomIndex]
self.middle.text = mname
self.middle.backgroundColor = mcolor
let middleColorRemoval = (colorArray.removeAtIndex(randomIndex))
print(middleColorRemoval)
var (rcolor, rname) = colorArray[randomIndex]
self.right.text = rname
self.right.backgroundColor = rcolor
let rightColorRemoval = (colorArray.removeAtIndex(randomIndex))
print(rightColorRemoval)
You can store an array of tuples that include both the actual UIColor and the string value. This makes it so you can provide any string value you want:
let colorArray = [(UIColor.redColor(), "Red"), (UIColor.greenColor(), "Green"), (UIColor.blueColor(), "Blue")]
Then, to access a random color:
let (color, name) = colorArray[randomIndex]
self.left.text = name
self.left.backgroundColor = color
...
It seems to me that your code doesn't actually remove random colors. Here's how you would actually do it (one of many ways):
let random = { () -> Int in
return Int(arc4random_uniform(UInt32(colorArray.count)))
} // makes random number, you can make it more reusable
let (leftColor, leftName) = colorArray.removeAtIndex(random()) // removeAtIndex: returns the removed tuple
let (middleColor, middleName) = colorArray.removeAtIndex(random())
let (rightColor, rightName) = colorArray.removeAtIndex(random())

Usage for plotAreaViewPointForPlotPoint in CorePlot 1.5.1

I'm trying to add something like UIPopoverController into the barPlot with coreplot 1.5.1 and swift. Like this one Core Plot: How to present popover from a bar selected by the user
So we need to know the point where the selected bar is ,But looks like some functions are different, like plotAreaViewPointForPlotPoint. In 1.5.1, there are two parameters:
And I'm try to find the right way to use it but failed, here is my code:
func barPlot(plot: CPTBarPlot!, barWasSelectedAtRecordIndex idx: UInt, withEvent event: UIEvent!) {
// Remove all the annotations
graphView.hostedGraph.plotAreaFrame.plotArea.removeAllAnnotations()
// Setup a style for the annotation
let hitAnnotationTextStyle = CPTMutableTextStyle.textStyle() as! CPTMutableTextStyle
hitAnnotationTextStyle.color = CPTColor.whiteColor()
hitAnnotationTextStyle.fontSize = 12.0;
hitAnnotationTextStyle.fontName = FONT_HEITI;
// Determine point of symbol in plot coordinates
let anchorPoint = [Int(idx),0]
// Add annotation
// First make a string for the y value
let string = "\(idx),values is:\(mArray.objectAtIndex(Int(idx)))"
// Now add the annotation to the plot area
let textLayer = CPTTextLayer(text: string, style: hitAnnotationTextStyle)
// popview, DxPopover is something like UIPopover Controller in iPhone
var popView = DXPopover()
annotationLabel.text = string
var pointers = [NSDecimal](count: 2, repeatedValue: CPTDecimalFromUnsignedInteger(0))
pointers[0] = CPTDecimalFromUnsignedInteger(idx)
var plotPointer: UnsafeMutablePointer<NSDecimal> = UnsafeMutablePointer<NSDecimal>.alloc(pointers.count)
plotPointer.initializeFrom(pointers)
var popPoint = graphView.hostedGraph.defaultPlotSpace.plotAreaViewPointForPlotPoint(plotPointer, numberOfCoordinates: idx)
popView.showAtPoint(popPoint, popoverPostion: DXPopoverPosition.Down, withContentView: self.annotationView, inView: graphView)
// selectedBarAnnotation = CPTPlotSpaceAnnotation(plotSpace: graphView.hostedGraph.defaultPlotSpace, anchorPlotPoint: anchorPoint)
// selectedBarAnnotation!.contentLayer = textLayer
// selectedBarAnnotation!.displacement = CGPointMake(0.0, -15.0)
// graphView.hostedGraph.plotAreaFrame.plotArea.addAnnotation(selectedBarAnnotation)
}
And it will crush at this line:
var popPoint = graphView.hostedGraph.defaultPlotSpace.plotAreaViewPointForPlotPoint(plotPointer, numberOfCoordinates: idx)
SO, HOW CAN I GET THE RIGHT CGPOINT?
Thanks very much!
=================EDIT===================
I change my codes to this, and can get the right point, Thanks to #Bannings
var popView = DXPopover()
annotationLabel.text = string
var pointers = [NSDecimal](count: 2, repeatedValue: CPTDecimalFromUnsignedInteger(0))
let plotXvalue = self.numberForPlot(plot, field: UInt(CPTScatterPlotFieldX.value), recordIndex: idx)
pointers[0] = CPTDecimalFromFloat(plotXvalue.floatValue)
println("\(CPTDecimalFromUnsignedInteger(idx))")
let plotspace = graphView.hostedGraph.defaultPlotSpace
println("\(plotspace.numberOfCoordinates)")
var popPoint = plotspace.plotAreaViewPointForPlotPoint(&pointers, numberOfCoordinates: plotspace.numberOfCoordinates)
popView.showAtPoint(popPoint, popoverPostion: DXPopoverPosition.Down, withContentView: self.annotationView, inView: graphView)
Try this:
var popPoint = graphView.hostedGraph.defaultPlotSpace.plotAreaViewPointForPlotPoint(&pointers, numberOfCoordinates: idx)

Dictionary doesn't recognize key type (Updated)

I have
func keyboardWillShow(aNotification: NSNotification) {
//Collect information about keyboard using its notification.
let info = aNotification.userInfo
let duration = (info[UIKeyboardAnimationDurationUserInfoKey] as NSValue) as Double
let curve : AnyObject? = info[UIKeyboardAnimationCurveUserInfoKey]
let kbFrame : AnyObject? = (info[UIKeyboardFrameEndUserInfoKey] as NSValue).CGRectValue().size
}
How can I get these to be read without the
"[NSObject : AnyObject]? does not have a member named 'subscript' " error?
In beta versions of xCode this had worked, but as of xCode 6.1 it no longer works properly.
userInfo is optional Dictionary, so you can use optional binding to unwrap value. And CGSize is a struct, not a object, so change AnyObject to CGSize.
if let info = aNotification.userInfo {
let duration = (info[UIKeyboardAnimationDurationUserInfoKey] as NSValue) as Double
let curve : AnyObject? = info[UIKeyboardAnimationCurveUserInfoKey]
let kbFrame: CGSize = (info[UIKeyboardFrameEndUserInfoKey] as NSValue).CGRectValue().size
}

Resources