I have modified slightly the original instructions from Michael Garron Hospital mask challenge. #1000masks The inside pocket is to allow for a filter to be added. They suggest: Vacuum cleaner filters, coffee filters, paper towel or Kleenex. They recommend that the masks be washed daily in hot water and detergent.
Wire: MGH suggested a twist tie, but I used a 4” piece of pipe cleaner and turned the sharp ends under.
Cutting instructions:
Child – 1 piece of outside fabric 22cm x 15cm (8 3/4” x 6) 1 piece of inside fabric 20cm x 13cm (8” x 5 1/4”) 2 pieces of 3cm wide elastic 15cm (5”) or 2 hair elastics cut open
Woman – 1 piece of outside fabric 23cm x 16cm (9” x 6 1/4”) 1 piece of inside fabric 22cm x 15cm (8 1/4” x 5 1/2”) 2 pieces of 3cm wide elastic 16cm (6”) or 2 hair elastics cut open
Man – 1 piece of outside fabric 24cm x 17cm (9 1/2” x 6 3/4” 1 piece of inside fabric 20cm x 13cm (8 3/4” x 6”) 2 pieces of 3cm wide elastic 17cm (6 1/2”) or 2 hair elastics cut open
Back in February 2015, my article on Touch ID was published on raywenderlich.com. It was written in Swift for Xcode 8. Every year or so, I would update the article while I was an author on the iOS Team. Here’s a link to the latest version — How To Secure iOS User Data: The Keychain and Biometrics – Face ID or Touch ID. A few months ago, I had to update one of my own apps for iOS 13 with Apple’s biometric identification framework, Local Authentication. Incidentally, my app was also still supporting Objective-C. Here’s follow up on what I had to change. As a bonus you can also take your user to Settings in case they have disabled
First thing is to add Local Authentication at the top of the Login view controller.
- (IBAction)touchIDAction:(id)sender { LAContext *myContext = [[LAContext alloc] init]; NSError *authError = nil; NSString *myLocalizedReasonString = @"Used for quick and secure access to the test app"; //... }
After that we need to check if the device can support biometrics with canEvaluatePolicy and have an error ready.
Inside the touchIDAction add:
if ([myContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&authError]) { // 1. successful steps } else { // 2. Oops. There's a error! }
Inside the canEvaluatePolicy, we’ll use evaluatePolicy:localizedReason:reply. The reply will have a block that either succeeds or fails with our error.
// 1. successful steps. [myContext evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics localizedReason:myLocalizedReasonString reply:^(BOOL success, NSError *error) { if (success) { dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){ //Background Thread dispatch_async(dispatch_get_main_queue(), ^(void){ //Run UI Updates // using a Keychain utility method to get the email and password NSString *passwordFound = [KeychainUtils getPasswordForUsername:self->emailTextField.text andServiceName:@"My_app" error:nil]; self->passwordTextField.text = passwordFound; self->usingSecureID = true; // a Bool I added to keep track [self loginAction:nil]; [NSLog showWithStatus:@"Logging_In"]; }); }); } else { // User did not authenticate successfully, look at error and take appropriate action //I'm using a showAlert method to bring up a UIAlertViewController [self showAlert: @"There was a problem verifying your identity." withTitle:@"Error!"]; return; } }];
What do we do if there is an error enabling Face ID/Touch ID? It could be because the user has disabled the feature. What’s new is that we can now take the user to your application settings — without a hack.
Initially you can pop up an alert to inform the user. Added to UIKit in iOS 8, UIApplicationOpenSettingsURLString lets you add a button to the alert that will take the user to your app in Settings, where they can enable Face ID/Touch ID.
// Could not evaluate policy; look at authError and present an appropriate message to user NSString *title = @"Error!"; NSString *message = @"Your device cannot authenticate using TouchID."; UIAlertController *alert = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert]; UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { // do we need to return animation? }]; // open your app in Settings NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString]; UIApplication *application = [UIApplication sharedApplication]; NSString *settingTitle = @"Settings"; UIAlertAction* settingsAction = [UIAlertAction actionWithTitle:settingTitle style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { [application openURL:url options:@{} completionHandler:nil]; }]; [alert addAction:settingsAction]; [alert addAction:defaultAction]; [self presentViewController:alert animated:YES completion:nil]; return; }
The whole method would look like this:
- (IBAction)touchIDAction:(id)sender { LAContext *myContext = [[LAContext alloc] init]; NSError *authError = nil; NSString *myLocalizedReasonString = @"Used for quick and secure access to the test app"; if ([myContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&authError]) { // 1. successful steps [myContext evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics localizedReason:myLocalizedReasonString reply:^(BOOL success, NSError *error) { if (success) { dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){ //Background Thread dispatch_async(dispatch_get_main_queue(), ^(void){ //Run UI Updates // using a Keychain utility method to get the email and password NSString *passwordFound = [KeychainUtils getPasswordForUsername:self->emailTextField.text andServiceName:@"My_app" error:nil]; self->passwordTextField.text = passwordFound; self->usingSecureID = true; // a Bool I added to keep track [self loginAction:nil]; [NSLog showWithStatus:@"Logging_In"]; }); }); } else { // User did not authenticate successfully, look at error and take appropriate action //I'm using a showAlert method to bring up a UIAlertViewController [self showAlert: @"There was a problem verifying your identity." withTitle:@"Error!"]; return; } }]; } else { // 2. Oops. There's a error! // Could not evaluate policy; look at authError and present an appropriate message to user NSString *title = @"Error!"; NSString *message = @"Your device cannot authenticate using TouchID."; UIAlertController *alert = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert]; UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { // do we need to return animation? }]; // open your app in Settings NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString]; UIApplication *application = [UIApplication sharedApplication]; NSString *settingTitle = @"Settings"; UIAlertAction* settingsAction = [UIAlertAction actionWithTitle:settingTitle style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { [application openURL:url options:@{} completionHandler:nil]; }]; [alert addAction:settingsAction]; [alert addAction:defaultAction]; [self presentViewController:alert animated:YES completion:nil]; return; } } }
I was working on a cleanly installed Mac after migrating user accounts onto it. My account is not the primary admin account (eg. UID 501). For some reason Xcode was installed with all the permissions set to that primary user, who has yet to log onto this Mac!
I have been having multiple issues trying to get Xcode to build on this Mac — my traveling Mac. I like to leave my bread and butter Mac at home and travel with an 11 inch MacBook Air. Primarily because any other Mac cannot be opened on an airplane, in Economy. I cannot afford to fly business class since the Indie-Apocalypse hit in 2014.
So the owner permissions were all f’ed up, where Xcode does it’s build business. The last straw was the “Command CompileAssetCatalog” failure.
The fix is to change the permissions on the Xcode folder in my own home Library (which all files should be all owed my username.) Pro Tip: replace your username where you see mine — tmitra
cd /Users/tmitra/Library/Developer/Xcode/UserData ls -la
Checking the ownership of this folder showed I was not the owner. So I stepped back and fixed the permissions on the Xcode directory here:
sudo chown -R tmitra ~/Library/Developer/Xcode
Build and Run.
FWIW I also had to fix permissions elsewhere:
Error: Failed to create temporary directory: /Library/Developer/Xcode/UserData/IB Support/Simulator Devices/
Final Cut Pro projects can eat up a lot of disk space. When a project is complete, it sure is nice to package up the files and move them to another drive.
I spent a couple of hours this morning, investigating how to archive projects in Final Cut Pro 10.1.4 this morning. I found several resources that propertied to explain step by step how to go about doing this exact thing. However Apple must have changed the menu choices at some point, and the menu options and views have changed. So here is how I have figured how to combine the best of the previous methods with how the app works today. Maybe this will help you out.
Start by opening Disk Utility (inside Applications > Utilities folder).
Create a new disk image.
Click on New Image (or choose File > New > New Blank Image ). Enter a meaningful name in the Save As: field. Also enter that same name in the Name: field. (So that you don’t end up with the meaningless Disk Image name.)
From Size: pulldown choose Custom. The the dialog that opens choose GB and enter a size like 5 GB. The beauty of a sparse disk image is that it does not take up that amount of space, but can grow to that size if you need it to. Press Ok to save this setting.
In the Image Format: choose sparse disk image.
If you are happy with the location (Where:) you can press Create.
Disk Utility will create the sparse disk image and mount it on the Desktop. You can now use the disk image in Final Cut Pro X.
Copying Final Cut Project files to the Sparse Disk Image
OpenFinal Cut Pro 10.1.4. (or higher) From the File menu, choose New > New Library
Final Cut Pro will create the new Library with a default event (with today’s date.) You can delete that once you copy over at least one of the events you want to archive.
Preparing Projects to Archive.
Select the Event that you want to archive and choose Delete Generated Event Files. These are the files that FCP makes while you work on the projects.
Check Delete Render File and choose All. You can always recreate these if you work on the project later.
Next, with the Event selected, Control Click and choose Consolidate Event Files… from the contextual menu.
Make sure that Optimized Media and Proxy Media are not selected. You don’t need to archive these working files with the project.
This step will copy all of the original source files into the project. If you are like me and you link files into your projects, you will want to consolidate and archive a copy of the originals with the event. Later you can remove the files, if a copy remains elsewhere on your disk (that’s up to you and not covered here.) After all the idea is to free up the space.
You can check that the files are copied into the project, by Control Clicking and choosing Reveal in Finder. In the window that opens you can Command click on the Original Folders and reveal the path.
path to Originals
As you can see in the image above, Final Cut Pro stores the Original Files inside an Event folder, inside a Project folder, inside your Home folder’s Movies folder.
Once the files have been consolidated here, you are ready to copy this event to the sparse disk image we made above.
Drag the Event files to the Archive Library in FCP
Select the Event and Drag it onto the Library you made on the Archive sparse disk image. The cursor will change to green + to indicate that you are “copying” the Event.
You will see the status indicator change to indicate the progress of copying the files.
You can also open Background Tasks (Cmd 9) from the Window menu to see the progress of the copying.
When the Media Management task of copying over the files is complete, you can continue to copy over more events. You can see the amount of space available on the sparse disk image with the status bar in the Finder. (You can Show/Hide the status bar from the View menu in the Finder.)
Pro Tip: You can examine the contents of the Archive on the disk image by Cmd Clicking and choosing Show Package Contents. Remember look, don’t touch – you are peeling inside the Final Cut Pro X project itself.
Look! Don’t touch.
Cleaning up and Putting Away the Archive
When you are satisfied that the project has been copied to the sparse disk image you can close the Archive Library. You can do this by Control Click on the Archive and choose Close Library “name you chose”
Then Quit Final Cut Pro, so that you can “eject” the sparse image. (The Finder will say the disk is in use if FCP is still open.)
Eject the disk image and then you can copy/move the sparse disk image file to another drive or server.
Removing the project from Final Cut Pro – with caution.
Note:You accept responsibility if you remove the original project without backing up or previously archiving.
If you are absolutely sure that you have safely archived the project as mentioned above. You can remove the original project by Control Clicking on the Event and choosing Move To Trash. This step will remove the event and delete all of the consolidated files.