Home Blog

Defending mutable state with Mutex in Swift – Donny Wals


When you begin utilizing Swift Concurrency, actors will primarily turn into your normal selection for safeguarding mutable state. Nevertheless, introducing actors additionally tends to introduce extra concurrency than you meant which may result in extra advanced code, and a a lot more durable time transitioning to Swift 6 in the long term.

While you work together with state that’s protected by an actor, you need to to take action asynchronously. The result’s that you just’re writing asynchronous code in locations the place you would possibly by no means have meant to introduce concurrency in any respect.

One method to resolve that’s to annotate your for instance view mannequin with the @MainActor annotation. This makes certain that every one your code runs on the principle actor, which implies that it is thread-safe by default, and it additionally makes certain that you could safely work together together with your mutable state.

That mentioned, this may not be what you are searching for. You would possibly wish to have code that does not run on the principle actor, that is not remoted by world actors or any actor in any respect, however you simply wish to have an old school thread-safe property.

Traditionally, there are a number of methods by which we are able to synchronize entry to properties. We used to make use of Dispatch Queues, for instance, when GCD was the usual for concurrency on Apple Platforms.

Just lately, the Swift crew added one thing known as a Mutex to Swift. With mutexes, we now have an alternative choice to actors for safeguarding our mutable state. I say different, but it surely’s probably not true. Actors have a really particular function in that they shield our mutable state for a concurrent surroundings the place we would like code to be asynchronous. Mutexes, then again, are actually helpful after we don’t desire our code to be asynchronous and when the operation we’re synchronizing is fast (like assigning to a property).

On this submit, we’ll discover how you can use Mutex, when it is helpful, and the way you select between a Mutex or an actor.

Mutex utilization defined

A Mutex is used to guard state from concurrent entry. In most apps, there will likely be a handful of objects that may be accessed concurrently. For instance, a token supplier, an picture cache, and different networking-adjacent objects are sometimes accessed concurrently.

On this submit, I’ll use a quite simple Counter object to verify we don’t get misplaced in advanced particulars and specifics that don’t influence or change how we use a Mutex.

While you increment or decrement a counter, that’s a fast operation. And in a codebase the place. the counter is accessible in a number of duties on the similar time, we would like these increment and decrement operations to be secure and free from information races.

Wrapping your counter in an actor is sensible from a idea viewpoint as a result of we would like the counter to be shielded from concurrent accesses. Nevertheless, after we do that, we make each interplay with our actor asynchronous.

To considerably stop this, we may constrain the counter to the principle actor, however that implies that we’re at all times going to must be on the principle actor to work together with our counter. We would not at all times be on the identical actor after we work together with our counter, so we might nonetheless must await interactions in these conditions, and that is not superb.

So as to create a synchronous API that can also be thread-safe, we may fall again to GCD and have a serial DispatchQueue.

Alternatively, we are able to use a Mutex.

A Mutex is used to wrap a bit of state and it ensures that there is unique entry to that state. A Mutex makes use of a lock underneath the hood and it comes with handy strategies to be sure that we purchase and launch our lock rapidly and accurately.

After we attempt to work together with the Mutex‘ state, we now have to attend for the lock to turn into out there. That is just like how an actor would work with the important thing distinction being that ready for a Mutex is a blocking operation (which is why we must always solely use it for fast and environment friendly operations).

This is what interacting with a Mutex appears to be like like:

class Counter {
    personal let mutex = Mutex(0)

    func increment() {
        mutex.withLock { rely in
            rely += 1
        }
    }

    func decrement() {
        mutex.withLock { rely in
            rely -= 1
        }
    }
}

Our increment and decrement capabilities each purchase the Mutex, and mutate the rely that’s handed to withLock.

Our Mutex is outlined by calling the Mutex initializer and passing it our preliminary state. On this case, we cross it 0 as a result of that’s the beginning worth for our counter.

On this instance, I’ve outlined two capabilities that safely mutate the Mutex‘ state. Now let’s see how we are able to get the Mutex‘ worth:

var rely: Int {
    return mutex.withLock { rely in
        return rely
    }
}

Discover that studying the Mutex worth can also be performed withLock. The important thing distinction with increment and decrement right here is that as an alternative of mutating rely, I simply return it.

It’s completely important that we hold our operations inside withLock quick. We don’t wish to maintain the lock for any longer than we completely must as a result of any threads which can be ready for our lock or blocked whereas we maintain the lock.

We are able to increase our instance somewhat bit by including a get and set to our rely. This can permit customers of our Counter to work together with rely prefer it’s a standard property whereas we nonetheless have data-race safety underneath the hood:

var rely: Int {
    get {
        return mutex.withLock { rely in
            return rely
        }
    }

    set {
        mutex.withLock { rely in
            rely = newValue
        }
    }
}

We are able to now use our Counter as follows:

let counter = Counter()

counter.rely = 10
print(counter.rely)

That’s fairly handy, proper?

Whereas we now have a kind that is freed from data-races, utilizing it in a context the place there are a number of isolation contexts is a little bit of a problem after we opt-in to Swift 6 since our Counter doesn’t conform to the Sendable protocol.

The great factor about Mutex and sendability is that mutexes are outlined as being Sendable in Swift itself. Because of this we are able to replace our Counter to be Sendable fairly simply, and without having to make use of @unchecked Sendable!

closing class Counter: Sendable {
    personal let mutex = Mutex(0)

    // ....
}

At this level, we now have a fairly good setup; our Counter is Sendable, it’s freed from data-races, and it has a completely synchronous API!

After we attempt to use our Counter to drive a SwiftUI view by making it @Observable, this get somewhat difficult:

struct ContentView: View {
    @State personal var counter = Counter()

    var physique: some View {
        VStack {
            Textual content("(counter.rely)")

            Button("Increment") {
                counter.increment()
            }

            Button("Decrement") {
                counter.decrement()
            }
        }
        .padding()
    }
}

@Observable
closing class Counter: Sendable {
    personal let mutex = Mutex(0)

    var rely: Int {
        get {
            return mutex.withLock { rely in
                return rely
            }
        }

        set {
            mutex.withLock { rely in
                rely = newValue
            }
        }
    }
}

The code above will compile however the view gained’t ever replace. That’s as a result of our computed property rely is predicated on state that’s not explicitly altering. The Mutex will change the worth it protects however that doesn’t change the Mutex itself.

In different phrases, we’re not mutating any information in a method that @Observable can “see”.

To make our computed property work @Observable, we have to manually inform Observable after we’re accessing or mutating (on this case, the rely keypath). This is what that appears like:

var rely: Int {
    get {
        self.entry(keyPath: .rely)
        return mutex.withLock { rely in
            return rely
        }
    }

    set {
        self.withMutation(keyPath: .rely) {
            mutex.withLock { rely in
                rely = newValue
            }
        }
    }
}

By calling the entry and withMutation strategies that the @Observable macro provides to our Counter, we are able to inform the framework after we’re accessing and mutating state. This can tie into our Observable’s common state monitoring and it’ll permit our views to replace after we change our rely property.

Mutex or actor? How you can determine?

Selecting between a mutex and an actor isn’t at all times trivial or apparent. Actors are actually good in concurrent environments when you have already got a complete bunch of asynchronous code. When you do not wish to introduce async code, or while you’re solely defending one or two properties, you are in all probability within the territory the place a mutex makes extra sense as a result of the mutex won’t power you to write down asynchronous code wherever.

I may fake that it is a trivial determination and you need to at all times use mutexes for easy operations like our counter and actors solely make sense while you wish to have a complete bunch of stuff working asynchronously, however the determination normally is not that simple.

When it comes to efficiency, actors and mutexes do not fluctuate that a lot, so there’s not an enormous apparent efficiency profit that ought to make you lean in a single path or the opposite.

In the long run, your selection ought to be based mostly round comfort, consistency, and intent. When you’re discovering your self having to introduce a ton of async code simply to make use of an actor, you are in all probability higher off utilizing a Mutex.

Actors ought to be thought of an asynchronous software that ought to solely be utilized in locations the place you’re deliberately introducing and utilizing concurrency. They’re additionally extremely helpful while you’re attempting to wrap longer-running operations in a method that makes them thread-safe. Actors don’t block execution which implies that you’re utterly fantastic with having “slower” code on an actor.

When unsure, I wish to strive each for a bit after which I stick to the choice that’s most handy to work with (and infrequently that’s the Mutex…).

In Abstract

On this submit, you have realized about mutexes and the way you need to use them to guard mutable state. I confirmed you ways they’re used, once they’re helpful, and the way a Mutex compares to an actor.

You additionally realized somewhat bit about how one can select between an actor or a property that is protected by a mutex.

Making a selection between an actor or a Mutex is, for my part, not at all times simple however experimenting with each and seeing which model of your code comes out simpler to work with is an effective begin while you’re attempting to determine between a Mutex and an actor.

Kieran Norton, Deloitte’s US Cyber AI & Automation chief – Interview Sequence

0


Kieran Norton a principal (accomplice) at Deloitte & Touche LLP, is the US Cyber AI & Automation Chief for Deloitte. With over 25 years of in depth expertise and a strong expertise background, Kieran excels in addressing rising dangers, offering shoppers with strategic and pragmatic insights into cybersecurity and expertise danger administration.

Inside Deloitte, Kieran leads the AI transformation efforts for the US Cyber observe. He oversees the design, improvement, and market deployment of AI and automation options, serving to shoppers improve their cyber capabilities and undertake AI/Gen AI applied sciences whereas successfully managing the related dangers.

Externally, Kieran helps shoppers in evolving their conventional safety methods to help digital transformation, modernize provide chains, speed up time to market, scale back prices, and obtain different essential enterprise targets.

With AI brokers turning into more and more autonomous, what new classes of cybersecurity threats are rising that companies could not but absolutely perceive?

The dangers related to utilizing new AI associated applied sciences to design, construct, deploy and handle brokers could also be understood—operationalized is a unique matter.

AI agent company and autonomy – the flexibility for brokers to understand, determine, act and function unbiased of people –can create challenges with sustaining visibility and management over relationships and interactions that fashions/brokers have with customers, knowledge and different brokers.  As brokers proceed to multiply throughout the enterprise, connecting a number of platforms and providers with growing autonomy and resolution rights, this can develop into more and more tougher. The threats related to poorly protected, extreme or shadow AI company/autonomy are quite a few. This could embrace knowledge leakage, agent manipulation (by way of immediate injection, and many others.) and agent-to-agent assault chains.  Not all of those threats are here-and-now, however enterprises ought to take into account how they are going to handle these threats as they undertake and mature AI pushed capabilities.

AI Id administration is one other danger that ought to be thoughtfully thought of.  Figuring out, establishing and managing the machine identities of AI brokers will develop into extra complicated as extra brokers are deployed and used throughout enterprises. The ephemeral nature of AI fashions / mannequin parts which are spun up and torn down repeatedly below various circumstances, will end in challenges in sustaining these mannequin IDs.  Mannequin identities are wanted to observe the exercise and conduct of brokers from each a safety and belief perspective. If not carried out and monitored correctly, detecting potential points (efficiency, safety, and many others.) might be very difficult.

How involved ought to we be about knowledge poisoning assaults in AI coaching pipelines, and what are one of the best prevention methods?

Information poisoning represents considered one of a number of methods to affect / manipulate AI fashions throughout the mannequin improvement lifecycle. Poisoning usually happens when a nasty actor injects dangerous knowledge into the coaching set. Nevertheless, it’s necessary to notice that past specific adversarial actors, knowledge poisoning can happen as a result of errors or systemic points in knowledge technology.  As organizations develop into extra knowledge hungry and search for useable knowledge in additional locations (e.g., outsourced handbook annotation, bought or generated artificial knowledge units, and many others.), the potential of unintentionally poisoning coaching knowledge grows, and will not all the time be simply recognized.

Focusing on coaching pipelines is a main assault vector utilized by adversaries for each refined and overt affect. Manipulation of AI fashions can result in outcomes that embrace false positives, false negatives, and different extra refined covert influences that may alter AI predictions.

Prevention methods vary from implementing options which are technical, procedural and architectural.  Procedural methods embrace knowledge validation / sanitization and belief assessments; technical methods embrace utilizing safety enhancements with AI strategies like federated studying; architectural methods embrace implementing zero-trust pipelines and implementing strong monitoring / alerting that may facilitate anomaly detection. These fashions are solely pretty much as good as their knowledge, even when a company is utilizing the most recent and best instruments, so knowledge poisoning can develop into an Achilles heel for the unprepared.

In what methods can malicious actors manipulate AI fashions post-deployment, and the way can enterprises detect tampering early?

Entry to AI fashions post-deployment is often achieved via accessing an Software Programming Interface (API), an software by way of an embedded system, and/or by way of a port-protocol to an edge machine. Early detection requires early work within the Software program Improvement Lifecycle (SDLC), understanding the related mannequin manipulation strategies in addition to prioritized menace vectors to plot strategies for detection and safety. Some mannequin manipulation entails API hijacking, manipulation of reminiscence areas (runtime), and gradual / gradual poisoning by way of mannequin drift. Given these strategies of manipulation, some early detection methods could embrace utilizing finish level telemetry / monitoring (by way of Endpoint Detection and Response and Prolonged Detection and Response), implementing safe inference pipelines (e.g., confidential computing and Zero Belief ideas), and enabling mannequin watermarking / mannequin signing.

Immediate injection is a household of mannequin assaults that happen post-deployment and can be utilized for numerous functions, together with extracting knowledge in unintended methods, revealing system prompts not meant for regular customers, and inducing mannequin responses which will forged a company in a damaging gentle. There are number of guardrail instruments out there to assist mitigate the chance of immediate injection, however as with the remainder of cyber, that is an arms race the place assault strategies and defensive counter measures are continuously being up to date.

How do conventional cybersecurity frameworks fall brief in addressing the distinctive dangers of AI methods?

We usually affiliate ‘cybersecurity framework’ with steering and requirements – e.g. NIST, ISO, MITRE, and many others. A number of the organizations behind these have printed up to date steering particular to defending AI methods which might be very useful.

AI doesn’t render these frameworks ineffective – you continue to want to handle all the standard domains of cybersecurity — what it’s possible you’ll want is to replace your processes and packages (e.g. your SDLC) to handle the nuances related to AI workloads.  Embedding and automating (the place attainable) controls to guard in opposition to the nuanced threats described above is probably the most environment friendly and efficient manner ahead.

At a tactical degree, it’s price mentioning that the total vary of attainable inputs and outputs is usually vastly bigger than non-AI functions, which creates an issue of scale for conventional penetration testing and rules-based detections, therefore the concentrate on automation.

What key components ought to be included in a cybersecurity technique particularly designed for organizations deploying generative AI or massive language fashions?

When creating a cybersecurity technique for deploying GenAI or massive language fashions (LLMs), there is no such thing as a one-size-fits-all strategy. A lot is dependent upon the group’s general enterprise targets, IT technique, business focus, regulatory footprint, danger tolerance, and many others. in addition to the particular AI use instances into consideration.   An inner use solely chatbot carries a really totally different danger profile than an agent that might influence well being outcomes for sufferers for instance.

That mentioned, there are fundamentals that each group ought to deal with:

  • Conduct a readiness evaluation—this establishes a baseline of present capabilities in addition to identifies potential gaps contemplating prioritized AI use instances. Organizations ought to establish the place there are present controls that may be prolonged to handle the nuanced dangers related to GenAI and the necessity to implement new applied sciences or improve present processes.
  • Set up an AI governance course of—this can be internet new inside a company or a modification to present danger administration packages. This could embrace defining enterprise-wide AI enablement features and pulling in stakeholders from throughout the enterprise, IT, product, danger, cybersecurity, and many others. as a part of the governance construction. Moreover, defining/updating related insurance policies (acceptable use insurance policies, cloud safety insurance policies, third-party expertise danger administration, and many others.) in addition to establishing L&D necessities to help AI literacy and AI safety/security all through the group ought to be included.
  • Set up a trusted AI structure—with the stand-up of AI / GenAI platforms and experimentation sandboxes, present expertise in addition to new options (e.g. AI firewalls/runtime safety, guardrails, mannequin lifecycle administration, enhanced IAM capabilities, and many others.) will have to be built-in into improvement and deployment environments in a repeatable, scalable style.
  • Improve the SDLC—organizations ought to construct tight integrations between AI builders and the chance administration groups working to guard, safe and construct belief into AI options. This contains establishing a uniform/commonplace set of safe software program improvement practices and management necessities, in partnership with the broader AI improvement and adoption groups.

Are you able to clarify the idea of an “AI firewall” in easy phrases? How does it differ from conventional community firewalls?

An AI firewall is a safety layer designed to observe and management the inputs and outputs of AI methods—particularly massive language fashions—to stop misuse, defend delicate knowledge, and guarantee accountable AI conduct. In contrast to conventional firewalls that defend networks by filtering visitors based mostly on IP addresses, ports, and identified threats, AI firewalls concentrate on understanding and managing pure language interactions. They block issues like poisonous content material, knowledge leakage, immediate injection, and unethical use of AI by making use of insurance policies, context-aware filters, and model-specific guardrails. In essence, whereas a standard firewall protects your community, an AI firewall protects your AI fashions and their outputs.

Are there any present business requirements or rising protocols that govern using AI-specific firewalls or guardrails?
Mannequin communication protocol (MCP) shouldn’t be a common commonplace however is gaining traction throughout the business to assist deal with the rising configuration burden on enterprises which have a have to handle AI-GenAI resolution variety. MCP governs how AI fashions alternate data (together with studying) inclusive of integrity and verification. We are able to consider MCP because the transmission management protocol (TCP)/web protocol (IP) stack for AI fashions which is especially helpful in each centralized, federated, or distributed use instances. MCP is presently a conceptual framework that’s realized via numerous instruments, analysis, and tasks.

The area is transferring rapidly and we will count on it would shift fairly a bit over the subsequent few years.

How is AI reworking the sector of menace detection and response right now in comparison with simply 5 years in the past?

We’ve got seen the business safety operations heart (SOC) platforms modernizing to totally different levels, utilizing large high-quality knowledge units together with superior AI/ML fashions to enhance detection and classification of threats. Moreover, they’re leveraging automation, workflow and auto-remediation capabilities to cut back the time from detection to mitigation.  Lastly, some have launched copilot capabilities to additional help triage and response.

Moreover, brokers are being developed to satisfy choose roles throughout the SOC.  As a sensible instance, we’ve got constructed a ‘Digital Analyst’ agent for deployment in our personal managed providers providing.   The agent serves as a degree one analyst, triaging inbound alerts, including context from menace intel and different sources, and recommending response steps (based mostly on in depth case historical past) for our human analysts who then assessment, modify if wanted and take motion.

How do you see the connection between AI and cybersecurity evolving over the subsequent 3–5 years—will AI be extra of a danger or an answer?
As AI evolves over the subsequent 3-5 years, it might probably assist cybersecurity however on the similar time, it might probably additionally introduce dangers. AI will develop the assault floor and create new challenges from a defensive perspective.  Moreover, adversarial AI goes to extend the viability, velocity and scale of assaults which is able to create additional challenges. On the flip aspect, leveraging AI within the enterprise of cybersecurity presents vital alternatives to enhance effectiveness, effectivity, agility and velocity of cyber operations throughout most domains—finally making a ‘battle hearth with hearth’ situation.

Thanks for the good interview, readers might also want to go to Deloitte.

ios – Crash when importing or deleting photographs with AWSS3Manager in Swift 6 – attainable completion block problem?


I am working with AWS S3 in an iOS app utilizing Swift 6. I’ve a singleton class AWSS3Manager that handles importing and deleting photographs, movies, and different recordsdata. Nonetheless, after migrating to Swift 6, I am experiencing random crashes when importing or deleting a number of photographs. The difficulty appears to be associated to completion blocks being referred to as inappropriately or a number of occasions, particularly throughout picture add or when iterating by means of uploadImages.

@MainActor
class AWSS3Manager{

    static let shared = AWSS3Manager() // 4
    non-public init () {
        initializeS3()
    }
    let bucketName = "Bucket_Name" //5

    func initializeS3() {
        if S3Key == "" || S3SecretKeyName == "" {
//            if let topVC = UIApplication.topViewController() {
//                topVC.showError("One thing went unsuitable!")
//            }
            debugPrint("AWS initialisation Error")
            return
        }
        let credentials = AWSStaticCredentialsProvider(accessKey: S3Key, secretKey: S3SecretKeyName)
        let configuration = AWSServiceConfiguration(area: AWSRegionType.USEast1, credentialsProvider: credentials)

        AWSServiceManager.default().defaultServiceConfiguration = configuration
    }

    func uploadImages(photographs: [UIImage], paths: [String], completion: @escaping(_ response: Any?, _ error: Error?) -> Void){

        if photographs.rely == 0 || InternetConnectionManager.isConnectedToNetwork() == false {
            completion(nil, nil)
        }
        if AWSServiceManager.default().defaultServiceConfiguration == nil {
            initializeS3()
            let error = NSError(area: "AWS", code: 1001, userInfo: [NSLocalizedDescriptionKey: "AWS is not initialized."])
            completion(nil, error)
            return
        }
        var counter: Int = 0
        photographs.enumerated().forEach { i,picture in
            let imageName: String = String(paths[i].cut up(separator: "/").final ?? "(UUID().uuidString).jpeg")
            if let imageData = picture.jpegData(compressionQuality: 0.3),
               let localUrl = attempt? saveDataToTempFolder(information: imageData, fileName: imageName){
                self.uploadfile(fileUrl: localUrl, fileName: paths[i], contenType: "picture", progress: nil) { response, error in
                    counter += 1
                    if counter == paths.rely {
                        completion(nil, error)
                    }
                }
            }else{
                counter += 1
                if counter == paths.rely {
                    completion(nil, nil)
                }
            }
        }
    }

    func deleteImage(path: String){
        if AWSServiceManager.default().defaultServiceConfiguration == nil {
            initializeS3()
            if let topVC = UIApplication.topViewController() {
                topVC.showError("One thing went unsuitable!")
            }
            return
        }
        let s3 = AWSS3.default()
        guard let deleteObjectRequest = AWSS3DeleteObjectRequest() else {
            return
        }
        deleteObjectRequest.bucket = S3BucketName
        deleteObjectRequest.key = path
        s3.deleteObject(deleteObjectRequest).continueWith { (process:AWSTask) -> AnyObject? in
            if let error = process.error {
                debugPrint("Error occurred: (error)")
                return nil
            }
            debugPrint("Deleted efficiently.")
            return nil
        }
    }

    func deleteAllImagesForUser(userID: String) {
        if AWSServiceManager.default().defaultServiceConfiguration == nil {
            initializeS3()
            if let topVC = UIApplication.topViewController() {
                topVC.showError("One thing went unsuitable!")
            }
            return
        }
        let s3 = AWSS3.default()
        let folderPath = "Receipts/(userID)/"

        let listObjectsRequest = AWSS3ListObjectsRequest()
        listObjectsRequest?.bucket = S3BucketName
        listObjectsRequest?.prefix = folderPath

        s3.listObjects(listObjectsRequest!).continueWith { (process) -> AnyObject? in
            if let error = process.error {
                debugPrint("Error occurred whereas itemizing objects: (error)")
                return nil
            }

            if let listObjectsOutput = process.outcome, let contents = listObjectsOutput.contents {
                for object in contents {
                    let deleteObjectRequest = AWSS3DeleteObjectRequest()
                    deleteObjectRequest?.bucket = S3BucketName
                    deleteObjectRequest?.key = object.key

                    s3.deleteObject(deleteObjectRequest!).continueWith { (deleteTask) -> AnyObject? in
                        if let error = deleteTask.error {
                            debugPrint("Error occurred whereas deleting object (object.key ?? ""): (error)")
                        } else {
                            debugPrint("Deleted (object.key ?? "") efficiently.")
                        }
                        return nil
                    }
                }
            } else {
                debugPrint("No objects present in folder (folderPath)")
            }
            return nil
        }
    }

    // Add video from native path url
    func uploadVideo(videoUrl: URL, progress: progressBlock?, completion: completionBlock?) {
        let fileName = self.getUniqueFileName(fileUrl: videoUrl)
        self.uploadfile(fileUrl: videoUrl, fileName: fileName, contenType: "video", progress: progress, completion: completion)
    }

    // Add auido from native path url
    func uploadAudio(audioUrl: URL, progress: progressBlock?, completion: completionBlock?) {
        let fileName = self.getUniqueFileName(fileUrl: audioUrl)
        self.uploadfile(fileUrl: audioUrl, fileName: fileName, contenType: "audio", progress: progress, completion: completion)
    }

    // Add recordsdata like Textual content, Zip, and so on from native path url
    func uploadOtherFile(fileUrl: URL, conentType: String, progress: progressBlock?, completion: completionBlock?) {
        let fileName = self.getUniqueFileName(fileUrl: fileUrl)
        self.uploadfile(fileUrl: fileUrl, fileName: fileName, contenType: conentType, progress: progress, completion: completion)
    }

    // Get distinctive file identify
    func getUniqueFileName(fileUrl: URL) -> String {
        let strExt: String = "." + (URL(fileURLWithPath: fileUrl.absoluteString).pathExtension)
        return (ProcessInfo.processInfo.globallyUniqueString + (strExt))
    }

    //MARK:- AWS file add
    // fileUrl :  file native path url
    // fileName : identify of file, like "myimage.jpeg" "video.mov"
    // contenType: file MIME sort
    // progress: file add progress, worth from 0 to 1, 1 for 100% full
    // completion: completion block when uplaoding is end, you'll get S3 url of add file right here
    non-public func uploadfile(fileUrl: URL, fileName: String, contenType: String, progress: progressBlock?, completion: completionBlock?) {
        if AWSServiceManager.default().defaultServiceConfiguration == nil {
            initializeS3()
            if let topVC = UIApplication.topViewController() {
                topVC.showError("One thing went unsuitable!")
            }
            let error = NSError(area: "AWS", code: 1001, userInfo: [NSLocalizedDescriptionKey: "AWS is not initialized."])
            completion?(nil, error)
            return
        }
        // Add progress block
        let expression = AWSS3TransferUtilityUploadExpression()
        expression.progressBlock = {(process, awsProgress) in
            guard let uploadProgress = progress else { return }
            DispatchQueue.major.async {
                uploadProgress(awsProgress.fractionCompleted)
            }
        }
        // Completion block
        var completionHandler: AWSS3TransferUtilityUploadCompletionHandlerBlock?
        completionHandler = { (process, error) -> Void in
            DispatchQueue.major.async(execute: {
                if error == nil {
                    let url = AWSS3.default().configuration.endpoint.url
                    let publicURL = url?.appendingPathComponent(self.bucketName).appendingPathComponent(fileName)
                    let presignedURL = self.getPreSignedURL(S3DownloadKeyName: fileName)
                    if let completionBlock = completion {
                        completionBlock(fileName, nil)
                    }
                } else {
                    if let completionBlock = completion {
                        completionBlock(nil, error)
                    }
                }
            })
        }
        // Begin importing utilizing AWSS3TransferUtility
        let awsTransferUtility = AWSS3TransferUtility.default()
        awsTransferUtility.uploadFile(fileUrl, bucket: bucketName, key: fileName, contentType: contenType, expression: expression, completionHandler: completionHandler).continueWith { (process) -> Any? in
            if let error = process.error {
                debugPrint("error is: (error.localizedDescription)")
            }
            if let _ = process.outcome {
                // your uploadTask
            }
            return nil
        }
    }
}

Worms, Springs, and Smooth Robots: Tiny Creatures Encourage Large Leaps

0


Researchers at Georgia Tech just lately unveiled a powerful achievement: a 5-inch-long mushy robotic that may catapult itself 10 toes into the air – the peak of a basketball hoop – with none legs. The design was impressed by the standard nematode, a tiny roundworm thinner than a human hair that may bounce many occasions its physique size. 

By pinching its physique into tight kinks, the worm shops elastic power after which abruptly releases it, flinging itself skyward or backward like an acrobatic gymnast. The engineers mimicked this movement. Their “SoftJM” robotic is basically a versatile silicone rod with a stiff carbon-fiber spine. Relying on the way it bends, it might leap ahead or backward – although it has no wheels or legs.

In motion, the nematode-inspired robotic coils up very similar to an individual squatting, then explosively unbends to leap. A high-speed digital camera present how the worm curves its head up and kinks in the course of its physique to hop backward, then straightens and kinks on the tail to leap ahead. 

The Georgia Tech workforce discovered that these tight bends – usually an issue in hoses or cables – truly let the worm and the robotic retailer much more power. As one researcher famous, kinked straws or hoses are ineffective, however a kinked worm acts like a loaded spring. Within the lab, the mushy robotic reproduced this trick: it “pinches” its center or tail, tenses up, after which releases in a burst (about one-tenth of a millisecond) to soar into the air.

Smooth Robots on the Rise

Smooth robotics is a younger however quickly rising subject that usually takes cues from nature. Not like inflexible steel machines, mushy robots are made from versatile supplies that may squeeze, stretch and adapt to their environment. Early milestones within the subject embrace Harvard’s Octobot – an autonomous robotic made totally of silicone and fluid channels, with no inflexible elements, impressed by octopus muscular tissues. Since then, engineers have constructed a menagerie of soppy machines: from worm-like crawlers and jellified grippers to wearable “exo-suits” and rolling vine-like robots. 

For instance, Yale researchers created a turtle-inspired mushy robotic whose legs change between floppy flippers and agency “land legs” relying on whether or not it’s swimming or strolling. At UCSB, scientists made a vine-like robotic that grows towards gentle utilizing solely light-sensitive “pores and skin” – it actually extends itself via slender areas like a plant stem. These and different bio-inspired improvements present how mushy supplies can create new modes of motion.

General, supporters say mushy robots can go locations conventional robots can not. The U.S. Nationwide Science Basis notes that adaptive mushy machines “discover areas beforehand unreachable by conventional robots” – even contained in the human physique. Some mushy robots have programmable “skins” that change stiffness or coloration to mix in or grip objects. Engineers are additionally exploring origami/kirigami strategies, shape-memory polymers, and different tips so these robots can reconfigure on the fly.

Engineering Versatile Movement

Making a mushy robotic transfer like an animal comes with massive challenges. With out arduous joints or motors, designers should depend on materials properties and intelligent geometry. For instance, Georgia Tech’s jumper needed to embrace a carbon-fiber backbone inside its rubbery physique to make the spring motion highly effective sufficient. Integrating sensors and management methods can be tough. As Penn State engineers level out, conventional electronics are stiff and would freeze a mushy robotic in place.

To make their tiny crawling rescue robotic “sensible,” they needed to unfold versatile circuits fastidiously throughout the physique so it may nonetheless bend. Even discovering power sources is more durable: some mushy robots use exterior magnetic fields or pressurized air as a result of carrying a heavy battery would weigh them down.

The nematode-inspired mushy robots from Georgia Tech (Photograph: Candler Hobbs)

One other hurdle is exploiting the precise physics. The nematode-robot workforce realized that kinks truly assist. In a traditional rubber tube, a kink shortly stops move; however in a mushy worm it slow-builds inside stress, permitting far more bending earlier than launch. By experimenting with simulations and even water-filled balloon fashions, the researchers confirmed that their versatile physique may maintain plenty of elastic power when bent, then unleash it in a single quick hop. The result’s exceptional: from relaxation the robotic can bounce 10 toes excessive, repeatably, by merely flexing its backbone. These breakthroughs – discovering methods to retailer and launch power in rubbery supplies – are typical of soppy robotics engineering.

Actual-World Hoppers and Helpers

What are all these mushy robots good for? In precept, they will deal with conditions too harmful or awkward for inflexible machines. In catastrophe zones, as an illustration, mushy bots can wriggle below rubble or into collapsed buildings to seek out survivors. Penn State confirmed a prototype magnetically managed mushy crawler that would navigate tight particles and even transfer via blood-vessel-sized channels.

In drugs, microscopic mushy robots may ship medicine immediately within the physique. In a single MIT research, a thread-thin mushy robotic was envisioned to drift via arteries and clear clots, probably treating strokes with out open surgical procedure. Harvard scientists are engaged on mushy wearable exoskeletons too – a light-weight inflatable sleeve that helped ALS sufferers carry a shoulder, instantly enhancing their vary of movement.

Area businesses are additionally eyeing mushy leapers. Wheels can get caught on sand or rocks, however a hopping robotic may vault over craters and dunes. NASA is even imagining novel jumpers for the Moon and icy moons. In a single idea, a soccer-ball-sized bot referred to as SPARROW would use steam jets (from boiled ice) to hop many miles throughout Europa or Enceladus. Within the low gravity of these moons, a small bounce goes a really good distance – scientists be aware {that a} robotic’s one-meter leap on Earth may carry it 100 meters on Enceladus. The concept is that dozens of those hoppers may swarm throughout alien terrain “with full freedom to journey” the place wheeled rovers would stall. Again on Earth, future mushy jumpers may assist in search-and-rescue missions by leaping over rivers, mud, or unstable floor that might cease standard robots.

Smooth robots are additionally discovering work in trade and agriculture. NSF factors out they may turn into secure helpers on manufacturing facility flooring or on farms, as a result of they comply if a human is in the best way. Researchers have even constructed mushy grippers that lightly choose delicate fruit with out bruising it. The flexibleness of soppy machines means they will act in locations too small or versatile for inflexible units.

Ultimately, specialists imagine mushy robotics will essentially change many fields. From worms to wearable fits to lunar hoppers, this analysis thread exhibits how finding out tiny creatures can yield massive jumps in know-how.

ios – Presenting customized alert on prime of all of the views together with sheets or full display screen cowl


I’m looking for a working answer for this downside for a very long time however can not seem to get any options on SO working in my case. SwiftUI’s ‘.alert’ modifier appears to current itself on prime of all of the views, however the customization of the alert components is so restricted attributable to which I needed to create a customized alert. My alert comprises icons and styled buttons.

My app is advanced, so sharing a brief pattern working instance. The app presents a MainView and there’ll all the time be a sheet over it whose peak may be adjusted (typically full display screen cowl as an alternative of sheet). Alerts may be introduced by MainView and by any of the sheet views. In any case, I need alert to be all the time on prime of sheet view (or full display screen cowl)

Right here I attempted presenting an alert (take into account Coloration.black.opacity.. as an alert in my code under) in 2 other ways.

  • A technique is utilizing ZStack in ContentView and even in MainView. In each
    the circumstances, the AlertView opens behind SheetView and does not cowl
    SheetView.
  • Second method is utilizing an AlertViewModifier in SheetView.
    With this, the alert will get introduced throughout the SheetView (as an alternative of
    over SheetView) such that I’m nonetheless in a position to work together with the
    MainView and in addition in a position to regulate peak of SheetView.

Pattern code:

import SwiftUI

class SampleViewModel: ObservableObject {
    @Printed var showSheet = false
    @Printed var panelDetent = PresentationDetent.medium
    @Printed var showZStackAlert: Bool = false
}

struct ContentViewA: View {
    @StateObject var viewModel: SampleViewModel = .init()
    @State non-public var showSheet: Bool = false
    var physique: some View {
        NavigationStack {
            ZStack {
                if viewModel.showZStackAlert {
                    AlertView()
                }
                
                MainView()
            }
        }
        .environmentObject(viewModel)
    }
}

/// Presenting customized alert from foremost ContentView
struct AlertView: View {
    var physique: some View {
        VStack {
            Coloration.black.opacity(0.5).edgesIgnoringSafeArea(.all)
        }
    }
}

struct MainView: View {
    @EnvironmentObject var viewModel: SampleViewModel
    @State non-public var showSheet: Bool = false
    var physique: some View {
        ZStack {
//            if viewModel.showZStackAlert {
//                AlertView()
//            }
//            
            VStack {
                Textual content("That is foremost view with all the time one sheet displayed")
            }
        }
        .onAppear {
            self.showSheet = true
        }
        .sheet(isPresented: $showSheet) {
            SheetView().environmentObject(viewModel)
        }
        // Extra sheets
        //.sheet(isPresented: $showSheetA) {
            //SheetViewA().environmentObject(viewModel)
        //}
    }
}

struct SheetView: View {
    @EnvironmentObject var viewModel: SampleViewModel
    @Surroundings(.presentationMode) non-public var presentationMode
    @State non-public var showAlert: Bool = false
    
    var physique: some View {
        NavigationStack {
            ZStack {
                Coloration.mint.opacity(0.1).edgesIgnoringSafeArea(.all)

                VStack {
                    Button {
                        viewModel.showZStackAlert = true
                        // self.showAlert = true
                    } label: {
                        Textual content("Faucet me to open alert")
                    }
                }
            }
        }
        .presentationDetents([.medium, .large], choice: $viewModel.panelDetent)
        .interactiveDismissDisabled(true)
        .presentationBackgroundInteraction(.enabled)
        .alertView(isPresented: $showAlert)
    }
}

/// Presenting customized alert utilizing Alert View Modifier
struct AlertViewModifier: ViewModifier {
    @Binding var isPresented: Bool
    
    init(isPresented: Binding) {
        self._isPresented = isPresented
    }

    func physique(content material: Content material) -> some View {
        content material
            .animation(nil, worth: self.$isPresented.wrappedValue)
            .overlay(self.$isPresented.wrappedValue ? Coloration.black.opacity(0.5) : nil)
            .overlay(self.$isPresented.wrappedValue ? alertContent() : nil)
            .animation(.default, worth: self.$isPresented.wrappedValue)
    }
    
    @ViewBuilder
    non-public func alertContent() -> some View {
        GeometryReader { geometry in
            if self.$isPresented.wrappedValue {
                VStack {
                    /// Contents of alert view
                }
                .fixedSize(horizontal: false, vertical: true)
                .place(x: geometry.measurement.width/2, y: geometry.measurement.peak/2)
                .body(minWidth: 350.0, maxWidth: 350.0)
            }
        }
    }
}

extension View {
    func alertView(isPresented: Binding) -> some View {
        return modifier(AlertViewModifier(isPresented: isPresented))
    }
}

How can I current AlertView all the time on prime of sheet view?