NSPredicate to filter beacon according to UUID, major and minor raising exception - nspredicate

I have a beacons array having a collection of CLBeacon and I would like to get only the beacon which matches a given uuid, major and minor in NSPredicate. Below is the code in Object C which is generating an exception because of UUID in the predicate. The code works fine if I remove the uuidPredicate from the query.
- (void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray<CLBeacon *> *)beacons inRegion:(CLBeaconRegion *)region{
NSPredicate *uuidPredicate = [NSPredicate predicateWithFormat:#"uuid.UUIDString == [c] %#", #"03672ce6-9272-48ea-ba54-0bf679217980"];
//NSPredicate *uuidPredicate = [NSPredicate predicateWithFormat:#"uuid == %#", #"03672ce6-9272-48ea-ba54-0bf679217980"];
NSPredicate *majorPredicate = [NSPredicate predicateWithFormat:#"major = %ld", 1];
NSPredicate *minorPredicate = [NSPredicate predicateWithFormat:#"minor = %ld", 3];
NSPredicate *compoundPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:#[uuidPredicate, majorPredicate, minorPredicate]];
NSArray *pointABeacon = [beacons filteredArrayUsingPredicate:compoundPredicate];
}
The beacons array is something like
beacons (
"CLBeacon (uuid:03672CE6-9272-48EA-BA54-0BF679217980, major:1, minor:1, proximity:1 +/- 0.07m, rssi:-61)",
"CLBeacon (uuid:03672CE6-9272-48EA-BA54-0BF679217980, major:1, minor:2, proximity:1 +/- 0.07m, rssi:-62)",
"CLBeacon (uuid:03672CE6-9272-48EA-BA54-0BF679217981, major:1, minor:3, proximity:2 +/- 1.64m, rssi:-53)"
)
The exception is
*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[< CLBeacon 0x1c401c410 > valueForUndefinedKey:]: this class is
not key value coding-compliant for the key uuid.'
How to filter the array with three parameters uuid, major and minor?

The error is clear:
A CLBeacon object doesn't have a property named uuid.
When you print a CLBeacon object, you might see "uuid", but that's not the real name of the property, it's proximityUUID
So:
NSPredicate *uuidPredicate = [NSPredicate predicateWithFormat:#"uuid.UUIDString == [c] %#", #"03672ce6-9272-48ea-ba54-0bf679217980"];
should be:
NSPredicate *uuidPredicate = [NSPredicate predicateWithFormat:#"proximityUUID.UUIDString == [c] %#", #"03672ce6-9272-48ea-ba54-0bf679217980"];

Related

Chaining replacements don't work in NSPredicate

The following code raises a question
NSPredicate * myPred = [NSPredicate predicateWithFormat:#"$my_var.employees.#count == 3"];
NSExpression * myExpr = [NSExpression expressionForKeyPath:#"$my_var.test"] ;
NSPredicate * myPredBis = [myPred predicateWithSubstitutionVariables:#{#"my_var" : myExpr}] ;
NSExpression * myExpr2 = [NSExpression expressionForKeyPath:#"self"] ;
NSPredicate * myFinalPred = [myPredBis predicateWithSubstitutionVariables:#{#"my_var": myExpr2}];
NSLog(#"%#", myFinalPred) ;
It prints
$my_var.test.employees.#count == 3
But we would like
self.test.employees.#count == 3
Why does this happen?
This is only a partial answer, but perhaps it helps to put you on the right path.
First, substituting $my_var by [NSExpression expressionForKeyPath:#"$my_var.test"]
does not work, because the latter expression treats $my_var as a plain key, not as
a variable.
But you can substitute one variable by another variable, using expressionForVariable:
NSPredicate * myPred = [NSPredicate predicateWithFormat:#"$my_var.employees.#count == 3"];
NSExpression * myExpr = [NSExpression expressionForVariable:#"another_var"] ;
NSPredicate * myPredBis = [myPred predicateWithSubstitutionVariables:#{#"my_var" : myExpr}] ;
Second, [NSExpression expressionForKeyPath:#"self"] treats "self" as an ordinary key, not as "the" self, i.e. the object onto which the predicate is applied. You probably
want:
NSExpression * myExpr2 = [NSExpression expressionForEvaluatedObject];
instead. Now you can chain the substitution:
NSPredicate * myFinalPred = [myPredBis predicateWithSubstitutionVariables:#{#"another_var": myExpr2}];
NSLog(#"%#", myFinalPred);
Output: employees.#count == 3 (the "self" part is just not printed).
OK, here is the solution to your problem. The tricky part is the second step.
I did not find a direct way to build a key-path expression that consists of a
variable ($my_var) combined with a normal key (test). But it can be done
by taking the left-hand side of a predicate:
NSPredicate * myPred = [NSPredicate predicateWithFormat:#"$my_var.employees.#count == 3"];
NSLog(#"%#", myPred) ;
// $my_var.employees.#count == 3
NSExpression *myExpr = [(NSComparisonPredicate *)[NSPredicate predicateWithFormat:#"$my_var.test == 0"] leftExpression];
NSPredicate * myPredBis = [myPred predicateWithSubstitutionVariables:#{#"my_var" : myExpr}] ;
NSLog(#"%#", myPredBis) ;
// $my_var.test.employees.#count == 3
NSExpression * myExpr2 = [NSExpression expressionForEvaluatedObject];
NSPredicate * myFinalPred = [myPredBis predicateWithSubstitutionVariables:#{#"my_var": myExpr2}];
NSLog(#"%#", myFinalPred) ;
// test.employees.#count == 3

Parsing JSON with AFNetworking give results with round brackets

Here is the simplified JSON file, I need to download it from a net service and parse results in a table!
EDIT: I provide now more precise code, cleaned and formatted by online tool:
{
"main": [
{
"id": 0, <--- float value
"type": "type0", <--- STRING value
"valueA": {
"valueA1": 1, <--- float value
"valueA2": 2, <--- float value
"valueA3": 3 <--- float value
},
"valueB": {
"valueB1": 1, <--- float value
"valueB2": 2 <--- float value
},
"valueC": [
{
"valueC1": "string0C1", <--- STRING value
"valueC2": 2, <--- float value
"valueC3": 3, <--- float value
}
]
},
FORMATTED by online tool jsonviewer.stack.hu:
I need to parse it with AFJSONRequestOperation, and I write this code:
NSMutableArray *main = [JSON objectForKey:#"main"];
arrayID = [main valueForKey:#"id"];
arrayType = [main valueForKey:#"type"];
NSMutableArray *arrayValueC = [main valueForKey:#"valueC"];
NSMutableString *stringC1 = [arrayValueC valueForKey:#"valueC1"];
// I CANT USE objectForKey, XCode give an exception -[__NSArrayI objectForKey:]: unrecognized selector sent to instance
NSLog(#"id: %#",arrayID);
NSLog(#"type: %#",arrayType);
NSLog(#"string: %#",stringC1);
When I parse, I get this results from NSLog:
id: (
0,
1,
2,
3,
4,
5,
6,
7,
8,
9
)
type: (
type0,
type1,
type2,
type3,
type4,
type5,
type6,
type7,
type8,
type9
)
string: (
(
"string0C1"
),
(
"string2C1"
),
(
"string2C1"
),
(
"string3C1"
),
(
"string4C1"
),
(
"string5C1"
),
(
"string6C1"
),
(
"string7C1"
),
(
"string8C1"
),
(
"string9C1"
)
)
As u can see its all perfect, I can extrapolate every value of ID (float) and TYPE (string), but I hate the round brackets in every object of the valueC1 string: how can I get the clean valueC1 without brackets and quotation marks? Please if u can provide some code. Thanks!
Don't use valueForKey:. Use objectForKey: instead. This is probably the major problem. But once you use it, you might run into new problem:
The following contains a problem that will manifest itself when arrayValueA is accessed the first time:
NSMutableArray *arrayValueA = [arrayMain objectForKey:#"valueA"];
The element stored at valueA is an object i.e. a dictionary and not an array.
Finally, your simplified JSON is invalid anyway. Several values are missing double quotes, e.g.:
"id": id0
should be:
"id": "id0"
You better shows the real JSON data and the real code.
Update:
You should be able to access the JSON data with the following code:
NSArray *main = [JSON objectForKey:#"main"];
NSDictionary* main0 = [main objectAtIndex:0];
arrayID = [main0 objectForKey:#"id"];
arrayType = [main0 objectForKey:#"type"];
NSArray *arrayValueC = [main objectForKey:#"valueC"];
NSDictionary *elem0 = [arrayValueC objectAtIndex:0];
NSString *stringC1 = [arrayValueC objectForKey:#"valueC1"];
NSLog(#"id: %#",arrayID);
NSLog(#"type: %#",arrayType);
NSLog(#"string: %#",stringC1);

NSPredicate performance, very slow

I have an NSPredicate which looks like
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"((strasse.checks CONTAINS [cd] YES) AND (raumattribute.schalter CONTAINS[cd] YES)) OR ((strasse.standort.ortcheck CONTAINS [cd] YES) AND (raumattribute.schalter CONTAINS[cd] YES)) OR ((strasse.standort.ortcheck CONTAINS [cd] YES) AND(raumattribute.schalter CONTAINS[cd] NO) OR (strasse.checks CONTAINS [cd] YES) AND (raumattribute.schalter CONTAINS[cd] NO)) OR (strasse.standort.ortcheck CONTAINS [cd] NO)"];
But the performance is very very slow. Is there a way to make it easier and faster?
First, you can simplify your predicate to look like this:
NSPredicate *predicate =
[NSPredicate predicateWithFormat:
#"(raumattribute.schalter CONTAINS YES OR raumattribute.schalter CONTAINS NO) AND \
(strasse.checks CONTAINS YES OR strasse.standort.ortcheck CONTAINS YES) OR \
strasse.standort.ortcheck CONTAINS NO"];
Then, if we assume raumattribute.schalter and strasse.standort.ortcheck contain boolean values only, we can simplify the predicate again:
NSPredicate *predicate =
[NSPredicate predicateWithFormat:
#"raumattribute.schalter.#count > 0 AND \
(strasse.checks CONTAINS YES OR strasse.standort.ortcheck.#count > 0) OR \
strasse.standort.ortcheck CONTAINS NO"];

How to get the list of filter names in CIFilter class?

I am using the following code for exposure adjustment and its working. I need the filter names for sharpen, denoise, highlighs, color temperature, shadows, blur, etc.
[CIFilter filterWithName: #"CIExposureAdjust"
keysAndValues: #"inputImage", [_imageView image], nil];
I was writing to your earlier post link to all filters. I will repeat: link to all filters.
And for example You need Blur effect. Blur is category and have 7 filters:
CIBoxBlur
CIDiscBlur
CIGaussianBlur
CIMedianFilter
CIMotionBlur
CINoiseReduction
CIZoomBlur.
And etc..
I found the list of names in CIFilter class, core image filters. here is the link names in CIFilter and the list of the filters.
Filters
CICategoryBlur
CIBoxBlur
CIDiscBlur
CIGaussianBlur
CIMaskedVariableBlur
CIMedianFilter
CIMotionBlur
CINoiseReduction
CICategoryColorAdjustment
CIColorClamp
CIColorControls
CIColorMatrix
CIColorPolynomial
CIExposureAdjust
CIGammaAdjust
CIHueAdjust
CILinearToSRGBToneCurve
CISRGBToneCurveToLinear
CITemperatureAndTint
CIToneCurve
CIVibrance
CIWhitePointAdjust
CICategoryColorEffect
CIColorCrossPolynomial
CIColorCube
CIColorCubeWithColorSpace
CIColorInvert
CIColorMap
CIColorMonochrome
CIColorPosterize
CIFalseColor
CIMaskToAlpha
CIMaximumComponent
CIMinimumComponent
CIPhotoEffectChrome
CIPhotoEffectFade
CIPhotoEffectInstant
CIPhotoEffectMono
CIPhotoEffectNoir
CIPhotoEffectProcess
CIPhotoEffectTonal
CIPhotoEffectTransfer
CISepiaTone
CIVignette
CIVignetteEffect
CICategoryCompositeOperation
CIAdditionCompositing
CIColorBlendMode
CIColorBurnBlendMode
CIColorDodgeBlendMode
CIDarkenBlendMode
CIDifferenceBlendMode
CIDivideBlendMode
CIExclusionBlendMode
CIHardLightBlendMode
CIHueBlendMode
CILightenBlendMode
CILinearBurnBlendMode
CILinearDodgeBlendMode
CILuminosityBlendMode
CIMaximumCompositing
CIMinimumCompositing
CIMultiplyBlendMode
CIMultiplyCompositing
CIOverlayBlendMode
CIPinLightBlendMode
CISaturationBlendMode
CIScreenBlendMode
CISoftLightBlendMode
CISourceAtopCompositing
CISourceInCompositing
CISourceOutCompositing
CISourceOverCompositing
CISubtractBlendMode
CICategoryDistortionEffect
CIBumpDistortion
CIBumpDistortionLinear
CICircleSplashDistortion
CICircularWrap
CIDroste
CIDisplacementDistortion
CIGlassDistortion
CIGlassLozenge
CIHoleDistortion
CILightTunnel
CIPinchDistortion
CIStretchCrop
CITorusLensDistortion
CITwirlDistortion
CIVortexDistortion
CICategoryGenerator
CIAztecCodeGenerator
CICheckerboardGenerator
CICode128BarcodeGenerator
CIConstantColorGenerator
CILenticularHaloGenerator
CIPDF417BarcodeGenerator
CIQRCodeGenerator
CIRandomGenerator
CIStarShineGenerator
CIStripesGenerator
CISunbeamsGenerator
CICategoryGeometryAdjustment
CIAffineTransform
CICrop
CILanczosScaleTransform
CIPerspectiveCorrection
CIPerspectiveTransform
CIPerspectiveTransformWithExtent
CIStraightenFilter
CICategoryGradient
CIGaussianGradient
CILinearGradient
CIRadialGradient
CISmoothLinearGradient
CICategoryHalftoneEffect
CICircularScreen
CICMYKHalftone
CIDotScreen
CIHatchedScreen
CILineScreen
CICategoryReduction
CIAreaAverage
CIAreaHistogram
CIRowAverage
CIColumnAverage
CIHistogramDisplayFilter
CIAreaMaximum
CIAreaMinimum
CIAreaMaximumAlpha
CIAreaMinimumAlpha
CICategorySharpen
CISharpenLuminance
CIUnsharpMask
CICategoryStylize
CIBlendWithAlphaMask
CIBlendWithMask
CIBloom
CIComicEffect
CIConvolution3X3
CIConvolution5X5
CIConvolution7X7
CIConvolution9Horizontal
CIConvolution9Vertical
CICrystallize
CIDepthOfField
CIEdges
CIEdgeWork
CIGloom
CIHeightFieldFromMask
CIHexagonalPixellate
CIHighlightShadowAdjust
CILineOverlay
CIPixellate
CIPointillize
CIShadedMaterial
CISpotColor
CISpotLight
CICategoryTileEffect
CIAffineClamp
CIAffineTile
CIEightfoldReflectedTile
CIFourfoldReflectedTile
CIFourfoldRotatedTile
CIFourfoldTranslatedTile
CIGlideReflectedTile
CIKaleidoscope
CIOpTile
CIParallelogramTile
CIPerspectiveTile
CISixfoldReflectedTile
CISixfoldRotatedTile
CITriangleKaleidoscope
CITriangleTile
CITwelvefoldReflectedTile
CICategoryTransition
CIAccordionFoldTransition
CIBarsSwipeTransition
CICopyMachineTransition
CIDisintegrateWithMaskTransition
CIDissolveTransition
CIFlashTransition
CIModTransition
CIPageCurlTransition
CIPageCurlWithShadowTransition
CIRippleTransition
CISwipeTransition
All you need to do is ask CIFilter for the filter names. You can then ask each filter for its attributes, which returns a dictionary that describes each input and output parameter that the filter accepts.
NSArray* filters = [CIFilter filterNamesInCategories:nil];
for (NSString* filterName in filters)
{
NSLog(#"Filter: %#", filterName);
NSLog(#"Parameters: %#", [[CIFilter filterWithName:filterName] attributes]);
}
For example, this is the output of the above code for the CIZoomBlur filter:
Filter: CIZoomBlur
Parameters: {
CIAttributeDescription = "Simulates the effect of zooming the camera while capturing the image.";
CIAttributeFilterCategories = (
CICategoryBlur,
CICategoryVideo,
CICategoryStillImage,
CICategoryBuiltIn
);
CIAttributeFilterDisplayName = "Zoom Blur";
CIAttributeFilterName = CIZoomBlur;
CIAttributeReferenceDocumentation = "http://developer.apple.com/cgi-bin/apple_ref.cgi?apple_ref=//apple_ref/doc/filter/ci/CIZoomBlur";
inputAmount = {
CIAttributeClass = NSNumber;
CIAttributeDefault = 20;
CIAttributeDescription = "The zoom-in amount. Larger values result in more zooming in.";
CIAttributeDisplayName = Amount;
CIAttributeIdentity = 0;
CIAttributeMin = 0;
CIAttributeSliderMax = 200;
CIAttributeSliderMin = 0;
CIAttributeType = CIAttributeTypeDistance;
CIUIParameterSet = CIUISetBasic;
};
inputCenter = {
CIAttributeClass = CIVector;
CIAttributeDefault = "[150 150]";
CIAttributeDescription = "The x and y position to use as the center of the effect.";
CIAttributeDisplayName = Center;
CIAttributeType = CIAttributeTypePosition;
CIUIParameterSet = CIUISetBasic;
};
inputImage = {
CIAttributeClass = CIImage;
CIAttributeDescription = "The image to use as an input image. For filters that also use a background image, this is the foreground image.";
CIAttributeDisplayName = Image;
CIUIParameterSet = CIUISetBasic;
};
outputImage = {
CIAttributeClass = CIImage;
};
}
Most of the time, though, you'll probably just use the docs.
May be you can try following method of CIFilter class
+ (NSArray *)filterNamesInCategory:(NSString *)category
In Swift (4.2, at the time of writing this), you can use this code to get all filter names:
For filters in a specified category:
CIFilter.filterNames(inCategory: "Name_of_the_category")
For filters in specified categories:
CIFilter.filterNames(inCategories: ["Name_of_the_category_1", "Name_of_the_category_2"])
For filters in all categories, just pass nil either in inCategory or inCategories:
CIFilter.filterNames(inCategory: nil)
or
CIFilter.filterNames(inCategories: nil)
All the functions above returns an Array of the filter names in String values:
[
"CIAccordionFoldTransition",
"CIAdditionCompositing",
"CIAffineClamp",
"CIAffineTile",
"CIAffineTransform",
"CIAreaAverage",
"CIAreaHistogram"...
]
NSLog(#"Distortion: %#", [CIFilter filterNamesInCategory:kCICategoryDistortionEffect]);
NSLog(#"Blurs: %#", [CIFilter filterNamesInCategory:kCICategoryBlur]);
NSLog(#"Color effects: %#", [CIFilter filterNamesInCategory:kCICategoryColorEffect]);
NSLog(#"Color adjustment: %#", [CIFilter filterNamesInCategory:kCICategoryColorAdjustment]);
NSLog(#"Built-in effects: %#", [CIFilter filterNamesInCategory:kCICategoryBuiltIn]);
iOS 14, Swift 5
Must confess not easy to read, but an answer that is comparable to the first one on Objective C.
for filtername in filters {
print("filter \(filtername)")
print("attributes \(CIFilter.init(name: filtername)?.attributes.keys.description)")
}
Produces this ...
filter CIAccordionFoldTransition
attributes Optional("[\"inputImage\", \"CIAttributeFilterDisplayName\", \"inputTargetImage\", \"CIAttributeFilterAvailable_iOS\", \"CIAttributeFilterAvailable_Mac\", \"inputNumberOfFolds\", \"inputFoldShadowAmount\", \"inputBottomHeight\", \"CIAttributeReferenceDocumentation\", \"inputTime\", \"CIAttributeFilterCategories\", \"CIAttributeFilterName\"]")
filter CIAdditionCompositing
attributes Optional("[\"CIAttributeFilterCategories\", \"CIAttributeFilterName\", \"CIAttributeFilterDisplayName\", \"inputImage\", \"CIAttributeReferenceDocumentation\", \"CIAttributeFilterAvailable_iOS\", \"CIAttributeFilterAvailable_Mac\", \"inputBackgroundImage\"]")
So the info is there in these long strings, you just need to pick it out :)
Noah Gilmore has a very handy filter tool to demo and document almost all cifilters & filter parms..
See on the app store 'CIFilter.io'. He also has the same on the web site https://cifilter.io
iOS 14, Swift 5
Here you can find also array of the CIFilter functions which is supported with the protocol.
CIFilter.hueSaturationValueGradient(),
CIFilter.linearGradient(),
CIFilter.radialGradient(),
CIFilter.smoothLinearGradient(),
CIFilter.sharpenLuminance(),
CIFilter.unsharpMask(),
CIFilter.dotScreen(),
CIFilter.hatchedScreen(),
CIFilter.lineScreen(),
CIFilter.bicubicScaleTransform(),
CIFilter.edgePreserveUpsample(),
CIFilter.keystoneCorrectionCombined(),
CIFilter.keystoneCorrectionHorizontal(),
CIFilter.keystoneCorrectionVertical(),
CIFilter.lanczosScaleTransform(),
CIFilter.perspectiveCorrection(),
CIFilter.perspectiveRotate(),
CIFilter.perspectiveTransform(),
CIFilter.perspectiveTransformWithExtent(),
CIFilter.straighten(),
CIFilter.accordionFoldTransition(),
CIFilter.barsSwipeTransition(),
CIFilter.copyMachineTransition(),
CIFilter.disintegrateWithMaskTransition(),
CIFilter.dissolveTransition(),
CIFilter.flashTransition(),
CIFilter.modTransition(),
CIFilter.pageCurlTransition(),
CIFilter.pageCurlWithShadowTransition(),
CIFilter.rippleTransition(),
CIFilter.swipeTransition(),
CIFilter.additionCompositing(),
CIFilter.colorBlendMode(),
CIFilter.colorBurnBlendMode(),
CIFilter.colorDodgeBlendMode(),
CIFilter.darkenBlendMode(),
CIFilter.differenceBlendMode(),
CIFilter.divideBlendMode(),
CIFilter.exclusionBlendMode(),
CIFilter.hardLightBlendMode(),
CIFilter.hueBlendMode(),
CIFilter.lightenBlendMode(),
CIFilter.linearBurnBlendMode(),
CIFilter.linearDodgeBlendMode(),
CIFilter.luminosityBlendMode(),
CIFilter.maximumCompositing(),
CIFilter.minimumCompositing(),
CIFilter.multiplyBlendMode(),
CIFilter.multiplyCompositing(),
CIFilter.overlayBlendMode(),
CIFilter.pinLightBlendMode(),
CIFilter.saturationBlendMode(),
CIFilter.screenBlendMode(),
CIFilter.softLightBlendMode(),
CIFilter.sourceAtopCompositing(),
CIFilter.sourceInCompositing(),
CIFilter.sourceOutCompositing(),
CIFilter.sourceOverCompositing(),
CIFilter.subtractBlendMode(),
CIFilter.colorAbsoluteDifference(),
CIFilter.colorClamp(),
CIFilter.colorControls(),
CIFilter.colorMatrix(),
CIFilter.colorPolynomial(),
CIFilter.colorThreshold(),
CIFilter.colorThresholdOtsu(),
CIFilter.depthToDisparity(),
CIFilter.disparityToDepth(),
CIFilter.exposureAdjust(),
CIFilter.gammaAdjust(),
CIFilter.hueAdjust(),
CIFilter.linearToSRGBToneCurve(),
CIFilter.sRGBToneCurveToLinear(),
CIFilter.temperatureAndTint(),
CIFilter.toneCurve(),
CIFilter.vibrance(),
CIFilter.whitePointAdjust(),
CIFilter.colorCrossPolynomial(),
CIFilter.colorCube(),
CIFilter.colorCubesMixedWithMask(),
CIFilter.colorCubeWithColorSpace(),
CIFilter.colorCurves(),
CIFilter.colorInvert(),
CIFilter.colorMap(),
CIFilter.colorMonochrome(),
CIFilter.colorPosterize(),
CIFilter.dither(),
CIFilter.documentEnhancer(),
CIFilter.falseColor(),
CIFilter.labDeltaE(),
CIFilter.maskToAlpha(),
CIFilter.maximumComponent(),
CIFilter.minimumComponent(),
CIFilter.paletteCentroid(),
CIFilter.palettize(),
CIFilter.photoEffectChrome(),
CIFilter.photoEffectFade(),
CIFilter.photoEffectInstant(),
CIFilter.photoEffectMono(),
CIFilter.photoEffectNoir(),
CIFilter.photoEffectProcess(),
CIFilter.photoEffectTonal(),
CIFilter.photoEffectTransfer(),
CIFilter.sepiaTone(),
CIFilter.thermal(),
CIFilter.vignette(),
CIFilter.vignetteEffect(),
CIFilter.xRay(),
CIFilter.bumpDistortion(),
CIFilter.bumpDistortionLinear(),
CIFilter.circleSplashDistortion(),
CIFilter.circularWrap(),
CIFilter.displacementDistortion(),
CIFilter.droste(),
CIFilter.glassDistortion(),
CIFilter.glassLozenge(),
CIFilter.holeDistortion(),
CIFilter.lightTunnel(),
CIFilter.ninePartStretched(),
CIFilter.ninePartTiled(),
CIFilter.pinchDistortion(),
CIFilter.stretchCrop(),
CIFilter.torusLensDistortion(),
CIFilter.twirlDistortion(),
CIFilter.vortexDistortion(),
CIFilter.affineClamp(),
CIFilter.affineTile(),
CIFilter.eightfoldReflectedTile(),
CIFilter.fourfoldReflectedTile(),
CIFilter.fourfoldRotatedTile(),
CIFilter.fourfoldTranslatedTile(),
CIFilter.glideReflectedTile(),
CIFilter.kaleidoscope(),
CIFilter.opTile(),
CIFilter.parallelogramTile(),
CIFilter.perspectiveTile(),
CIFilter.sixfoldReflectedTile(),
CIFilter.sixfoldRotatedTile(),
CIFilter.triangleKaleidoscope(),
CIFilter.triangleTile(),
CIFilter.twelvefoldReflectedTile(),
CIFilter.attributedTextImageGenerator(),
CIFilter.aztecCodeGenerator(),
CIFilter.barcodeGenerator(),
CIFilter.checkerboardGenerator(),
CIFilter.code128BarcodeGenerator(),
CIFilter.lenticularHaloGenerator(),
CIFilter.meshGenerator(),
CIFilter.pdf417BarcodeGenerator(),
CIFilter.qrCodeGenerator(),
CIFilter.randomGenerator(),
CIFilter.roundedRectangleGenerator(),
CIFilter.starShineGenerator(),
CIFilter.stripesGenerator(),
CIFilter.sunbeamsGenerator(),
CIFilter.textImageGenerator(),
CIFilter.blendWithAlphaMask(),
CIFilter.blendWithBlueMask(),
CIFilter.blendWithMask(),
CIFilter.blendWithRedMask(),
CIFilter.bloom(),
CIFilter.comicEffect(),
CIFilter.convolution3X3(),
CIFilter.convolution5X5(),
CIFilter.convolution7X7(),
CIFilter.convolution9Horizontal(),
CIFilter.convolution9Vertical(),
CIFilter.coreMLModel(),
CIFilter.crystallize(),
CIFilter.depthOfField(),
CIFilter.edges(),
CIFilter.edgeWork(),
CIFilter.gaborGradients(),
CIFilter.gloom(),
CIFilter.heightFieldFromMask(),
CIFilter.hexagonalPixellate(),
CIFilter.highlightShadowAdjust(),
CIFilter.lineOverlay(),
CIFilter.mix(),
CIFilter.pixellate(),
CIFilter.pointillize(),
CIFilter.saliencyMap(),
CIFilter.shadedMaterial(),
CIFilter.spotColor(),
CIFilter.spotLight(),
CIFilter.bokehBlur(),
CIFilter.boxBlur(),
CIFilter.discBlur(),
CIFilter.gaussianBlur(),
CIFilter.maskedVariableBlur(),
CIFilter.median(),
CIFilter.morphologyGradient(),
CIFilter.morphologyMaximum(),
CIFilter.morphologyMinimum(),
CIFilter.morphologyRectangleMaximum(),
CIFilter.morphologyRectangleMinimum(),
CIFilter.motionBlur(),
CIFilter.noiseReduction(),
CIFilter.zoomBlur] as [AnyObject]

Cocoa parse line of data like perl regex

What is the most efficient way to parse a line of data similar to how perl regex does? For example, if the line of data is: "username!ABCD!123-123-0000", I could use this perl expression to parse the data:
data =~ /([A-z]+)!([A-F]+)!([0-9]+)-(.+)/
This causes $1=username, $2=ABCD, $3=123, $4=123-0000
Is there a way to do this in Cocoa? Even solutions that predefine 4 NSString variables are fine.
Consider the following pattern:
username!tag!password
And the following requirements:
The username may only contain A-Z and a-z.
The tag may only contain A-F.
The password may only contain 0-9 and -.
One method to extract and validate the values:
NSString *input = #"username!ABCD!123-123-0000";
NSArray *split = [input componentsSeparatedByString:#"!"];
NSString *user = [split objectAtIndex:0];
NSString *tag = [split objectAtIndex:1];
NSString *pass = [split objectAtIndex:2];
NSCharacterSet *checkUser = [NSCharacterSet letterCharacterSet];
NSCharacterSet *checkTag = [NSCharacterSet characterSetWithCharactersInString:#"ABCDEF"];
NSCharacterSet *checkPass = [NSCharacterSet characterSetWithCharactersInString:#"0123456789-"];
if ( [[user stringByTrimmingCharactersInSet:checkUser] length] == 0 ) NSLog(#"User \"%#\" is valid.",user);
if ( [[tag stringByTrimmingCharactersInSet:checkTag ] length] == 0 ) NSLog(#"Tag \"%#\" is valid.", tag );
if ( [[pass stringByTrimmingCharactersInSet:checkPass] length] == 0 ) NSLog(#"Pass \"%#\" is valid.",pass);
Output:
User "username" is valid.
Tag "ABCD" is valid.
Pass "123-123-0000" is valid.
You may also consider using NSScanner or NSRegularExpression.

Resources