<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Mehmet Ateş on Medium]]></title>
        <description><![CDATA[Stories by Mehmet Ateş on Medium]]></description>
        <link>https://medium.com/@dev.mehmetates?source=rss-393f090c04a------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*eVG6ISOIA-onVkq-rItxPQ@2x.jpeg</url>
            <title>Stories by Mehmet Ateş on Medium</title>
            <link>https://medium.com/@dev.mehmetates?source=rss-393f090c04a------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Mon, 25 May 2026 06:15:50 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@dev.mehmetates/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Why did I code like this?]]></title>
            <link>https://medium.com/@dev.mehmetates/why-did-i-code-like-this-656bcd089086?source=rss-393f090c04a------2</link>
            <guid isPermaLink="false">https://medium.com/p/656bcd089086</guid>
            <category><![CDATA[chain-of-responsibility]]></category>
            <category><![CDATA[culture]]></category>
            <category><![CDATA[refactoring]]></category>
            <category><![CDATA[swift]]></category>
            <dc:creator><![CDATA[Mehmet Ateş]]></dc:creator>
            <pubDate>Sat, 02 Dec 2023 11:58:42 GMT</pubDate>
            <atom:updated>2023-12-02T11:58:42.457Z</atom:updated>
            <content:encoded><![CDATA[<p>Greetings to everyone. I often refactor my own projects and see what I can change. This time I was doing this at Socia, which was recently a guest on <a href="https://medium.com/@dev.mehmetates/chain-of-responsibility-pattern-in-swift-11fc0a0f9ec2">Chain Of Responsibility</a>. <strong>But some things caught my attention!</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/1*Fi1vFbQcoSQGJUOryr3zWg.png" /></figure><h3>Why?</h3><p>This word is truly magical. Why did I do this?</p><pre>protocol SociaHandler {<br>    associatedtype Request: FirebaseRequestStrategy<br>    <br>    var nextHandler: (any SociaHandler)? { get set }<br>    var request: Request? { get set }<br><br>    init(with handler: (any SociaHandler)?)<br><br>    func handle(_ onSuccess: (() -&gt; Void)?) async -&gt; LocalizedError?<br>}</pre><ul><li><strong>Why</strong> is Request a generic type and nextHandler not? (Reason is <a href="https://youtube.com/watch?v=Wa8xTSHX_PM&amp;si=ElduAGbuQBxQ0JZk">here</a>)</li><li><strong>Why</strong> am I returning LocalizedError?</li><li><strong>Why </strong>do I need a closure called onSuccess?</li></ul><pre>guard model.username.isEmpty == false else { return AuthError.emptyUsername }</pre><ul><li><strong>Why</strong> am I checking for a boolean value? (It made me feel awful)</li></ul><p>But this is a really beautiful thing. Because when I look at my code and I can think that something is wrong and I can fix my mistakes, it shows that I can continue my development. And that’s exactly what I want.</p><p>Let’s look at the problems together and find our solutions. One thing we need to pay attention to here is that there is something we want to fix. We learned something new, but should we really apply it?</p><h4>Why is Request a generic type and nextHandler not?</h4><p>Our first item talks about exactly this. Yes, if we can, it is more performant to get a generic type instead of any keyword. There is a video next to the article in which I explain this issue. (You may say that it might be better if this were done. If you have an idea, please let me know.)</p><p>But what I need here is exactly any handler. Because if a chain knew the generic form of the next chain, I would have to change the code so that something could be selected into the chain. And that doesn’t fit Solid’s O. So open closed.</p><p>Therefore, this is the answer to our first item. Using generics may cause reasons for me to change the code.</p><h4><strong>Why</strong> am I returning LocalizedError?</h4><p>The code here is “If an error is received, the error should be returned and I will check it and notify the user.” It is in the form. This isn’t a problem, but why is this a return type?</p><p>It would definitely be much better to use throws here. It shouldn’t be your job to debug. If an error occurs, just let the developer know about it. That’s why I updated the code here as follows.</p><pre>func handle() async throws</pre><p>Now I throw errors instead of returning them. What did I gain here?</p><p>This code performs only one task. In other words, it will do a job and this job may make mistakes. Then I don’t want results. What if I wanted to? Now in this case, I can just add return type and do what is necessary :)</p><h4><strong>Why </strong>do I need a closure called onSuccess?</h4><p>We can get a clue from the item above. We really don’t need this. Our protocol already has the full new handler.</p><p><strong>Old</strong></p><pre>func handle(_ onSuccess: (() -&gt; Void)?) async -&gt; LocalizedError? {<br>    guard let request else { return AuthError.requestError }<br>    guard request.storageData.isEmpty == false else { return await nextHandler?.handle(nil) }<br>    onSuccess?()<br><br>    let result: FirebaseResponse&lt;String&gt; = await FirestorageManagerManager.shared.request(request)<br>    if result.status == .success, let downloadLink = result.content {<br>        return await nextHandler?.handle { [weak self] in<br>            guard let handler = self?.nextHandler as? RegisterHandler&lt;RegisterRequest&gt; else { return }<br>            guard var requestModel = handler.request?.model else { return }<br>            requestModel.imagePath = downloadLink<br>            handler.request?.model = requestModel<br>        }<br>    }<br><br>    return AuthError.uploadError<br>}</pre><p><strong>New</strong></p><pre>func handle() async throws {<br>    guard let request else { throw AuthError.requestError }<br>    guard !request.storageData.isEmpty else {<br>        try await nextHandler?.handle()<br>        return<br>    }<br>    try await handleRequestResult(handleRequest(request))<br>    try await nextHandler?.handle()<br>}<br><br>private func handleRequestResult(_ response: FirebaseResponse&lt;String&gt;) throws {<br>    guard response.status == .success, let downloadLink = response.content else {<br>        throw AuthError.uploadError<br>    }<br>    <br>    guard let nextHandler = nextHandler as? RegisterHandler else {<br>        throw AuthError.unexpectedError<br>    }<br>    nextHandler.request?.model.imagePath = downloadLink<br>    self.nextHandler = nextHandler<br>}<br><br>private func handleRequest(_ request: UploadProfilePhotoRequest) async -&gt; FirebaseResponse&lt;String&gt; {<br>    await FirestorageManagerManager().request(request)<br>}</pre><p>The new code is longer. But it’s definitely more understandable. So much so that when I first looked at it, I said, where does the handle method work here?</p><p>Logically, when all operations are completed, the new handler should work. But here, even though the transactions are completed, we throw a new job to the other chain. And I think this is not the right approach.</p><p>We look at the next handler we have in the new code. And we change its model. Thus, all responsibility for uploading photos remains in this chain.</p><h4><strong>Why</strong> am I checking for a boolean value?</h4><p>This is entirely my fault. When writing your code, you usually write the easiest thing first, and then you can think about how to write it better. This is how I usually do it. But even though I reviewed my code here, doing long tasks definitely requires a break.</p><p>Even if I pay attention to my code while trying to create and explain the article, it seems overlooked and funny. Then let’s immediately update it with the code below and our problem will disappear.</p><pre>guard !request.storageData.isEmpty else {<br>    try await nextHandler?.handle()<br>    return<br>}</pre><h4>Summary and Closing</h4><p>If you ask why I wrote this article, it was definitely not to edit the code or share it. I could do this by updating the other article. The main theme here is definitely why we should use the word <strong>Why</strong>.</p><p>Especially when we learn new things, we feel deeply that our code is good and that we are improving ourselves. However, reviewing the code we wrote again (breaks are important here 🙂) gives a good answer to the question of whether we can take it further.</p><p>When you do this at regular intervals, you can see that it is improving and be able to criticize your own code. And you can continue to work and produce much more motivated.</p><p>Thank you for reading. Have a nice coding :)</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=656bcd089086" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Chain Of Responsibility Pattern In Swift]]></title>
            <link>https://medium.com/@dev.mehmetates/chain-of-responsibility-pattern-in-swift-11fc0a0f9ec2?source=rss-393f090c04a------2</link>
            <guid isPermaLink="false">https://medium.com/p/11fc0a0f9ec2</guid>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[chain-of-responsibility]]></category>
            <category><![CDATA[strategy-pattern]]></category>
            <category><![CDATA[refactoring]]></category>
            <dc:creator><![CDATA[Mehmet Ateş]]></dc:creator>
            <pubDate>Sat, 07 Oct 2023 10:13:47 GMT</pubDate>
            <atom:updated>2023-12-02T12:12:05.894Z</atom:updated>
            <content:encoded><![CDATA[<p>Greetings after a long time. In real life, we always encounter problems and somehow we look for a solution. We usually find a solution, but do we consider improving this solution? I must admit that we don’t do this much in real life.</p><p>But we should do this in our work. Then let’s take a look at the <strong>Chain of Responsibility</strong> that reins in complex sequential processes.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/1*gjTR8o9Lj7Zrx-LSU-8ZPw.png" /></figure><p>Let’s understand our problem first. I have a social media project called Socia. And it has a sign-up flow like every social media app. There are several responsibilities here.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/1*PFzusnJ6X7J9useAQ6bu4g.png" /></figure><p>The code containing part of the relevant flow is available below. And it’s messed up. There are a lot of controls in a single function, and it is very difficult to both read the code and make new developments at the moment.</p><pre>func autoLoginAfterRegister(name: String, surname: String, bio: String, image: UIImage, username: String, on system: AuthSystem) {<br>    system.isAuthProgress = true<br><br>    DispatchQueue.main.async {<br>        self.sgServices.uploadPhoto(image: image, imagePath: &quot;profile/profilePic.jpg&quot;, username: username) { saveResult in<br>            switch saveResult {<br>            case .failure(let saveError):<br>                system.failedTransaction(message: saveError.localizedDescription)<br>                return<br>            case .success(let imageURL):<br>                let userData = UserModel(username: username, name: name, surname: surname, bio: bio, imagePath: imageURL, bannerPath: nil, followers: nil, follows: nil, posts: nil).toMap()<br>                self.fsSaveService.saveUser(saveData: userData) { saveResult in<br>                    switch saveResult {<br>                    case .failure(let saveError):<br>                        system.failedTransaction(message: saveError.localizedDescription)<br>                    case .success:<br>                        if system.lastLoginID.isEmpty {<br>                            self.fsSaveService.saveBondedAcc(provider: system.lastLoginProvider, id: system.lastLoginID, username: username) { result in<br>                                switch result {<br>                                case.failure(let err):<br>                                    system.failedTransaction(message: err.localizedDescription)<br>                                case .success:<br>                                    system.successfulTransaction {<br>                                        system.username = username<br>                                        system.defaults.set(username, forKey: &quot;username&quot;)<br>                                        system.setCurrentUser()<br>                                        system.isEdittingRequired()<br>                                    }<br>                                }<br>                            }<br>                        } else {<br>                            system.failedTransaction(message: &quot;LOCAL_AN_ERROR_TAKED&quot;)<br>                            return<br>                        }<br>                    }<br>                }<br>            }<br>        }<br>    }<br>}</pre><p>Now let’s redesign this flow with the chain of responsibility and talk about the “+ — ” points.</p><p>First, let’s create a handler protocol. We do this to create each element in the chain.</p><pre>protocol SociaHandler {<br>    associatedtype Request: FirebaseRequestStrategy<br>    <br>    var nextHandler: (any SociaHandler)? { get set }<br>    var request: Request? { get set }<br><br>    init(with handler: (any SociaHandler)?)<br><br>    func handle(_ onSuccess: (() -&gt; Void)?) async -&gt; LocalizedError?<br>}</pre><p>My application works with Firebase and I have a manager managed with <strong>Strategy Pattern. </strong>The strategy I have adopted here is a base protocol for all my Firebase transactions.</p><blockquote>If you don’t have an idea about strategy pattern, you can look <a href="https://refactoring.guru/design-patterns/strategy/swift/example">here</a> or <a href="https://www.kodeco.com/books/design-patterns-by-tutorials/v3.0/chapters/5-strategy-pattern">here</a>.</blockquote><p>Let’s blend Pattern and my needs;</p><ul><li>Each chain can have a chain after it.</li><li>Each chain must contain a handler method.</li><li>Depending on the need, a request can be given to the relevant chain.</li></ul><p>So, let’s create the localizable error enum I need and the requests we will use in our chains.</p><pre>enum AuthError: LocalizedError {<br>    // Common Errors<br>    case unexpectedError<br>    case requestError<br>    case decodeError<br>    case uploadError<br>    <br>    // Required Fields<br>    case emptyEmail<br>    case emptyPassword<br>    case emptyRepassword<br>    case emptyUsername<br>    case emptyName<br>    case emptySurname<br>    <br>    // Password Related Errors<br>    case passwordTooShort<br>    case passwordsNotMatched<br>    <br>    // Related Errors<br>    case usernameAlreadyUsed<br>    case emailAlreadyUsed<br>    <br>    // Bio and Profile Photo Errors<br>    case bioTooLong<br><br>    var errorDescription: String? {<br>        switch self {<br>        case .unexpectedError:<br>            return &quot;An unexpected error occurred.&quot;<br>        case .requestError:<br>            return &quot;Request is nil or wrong.&quot;<br>        case .emptyEmail:<br>            return &quot;Email is empty.&quot;<br>        case .emptyPassword:<br>            return &quot;Password is empty.&quot;<br>        case .emptyRepassword:<br>            return &quot;Re-entered password is empty.&quot;<br>        case .emptyUsername:<br>            return &quot;Username is empty.&quot;<br>        case .emptyName:<br>            return &quot;Name is empty.&quot;<br>        case .emptySurname:<br>            return &quot;Surname is empty.&quot;<br>        case .passwordTooShort:<br>            return &quot;Password is too short.&quot;<br>        case .passwordsNotMatched:<br>            return &quot;Passwords do not match.&quot;<br>        case .usernameAlreadyUsed:<br>            return &quot;Username is already in use.&quot;<br>        case .emailAlreadyUsed:<br>            return &quot;Email is already in use.&quot;<br>        case .bioTooLong:<br>            return &quot;Bio is too long.&quot;<br>        case .decodeError:<br>            return &quot;Data decoding error.&quot;<br>        case .uploadError:<br>            return &quot;Upload error.&quot;<br>        }<br>    }<br>}</pre><p>These are the error situations we may encounter. There’s more. But I chose to keep it short for the sake of examples. When you see this is an example request.</p><pre>final class CheckUsernameRequest: FirestoreRequestStrategy {<br>    var model: RegisterModel<br>    <br>    var type: FirestoreRequestType {<br>        .get(model.username)<br>    }<br>    var referance: String = &quot;accDatas&quot;<br>    var data: [String: Any] {<br>        model.dictionary ?? [:]<br>    }<br>    <br>    init(_ model: RegisterModel) {<br>        self.model = model<br>    }<br>}</pre><p>Now it’s time to go into some detail. Let’s start writing our chains.</p><p>When we look at our flow, we see that the first chain is the part that controls the username. Let’s create a <strong>Check Username Handler</strong> for this.</p><pre>final class CheckUsernameHandler&lt;T: FirestoreRequestStrategy&gt;: SociaHandler {<br>    typealias Request = T<br><br>    var nextHandler: (any SociaHandler)?<br>    var request: T?<br><br>    init(with handler: (any SociaHandler)?) {<br>        nextHandler = handler<br>    }<br><br>    func handle(_ onSuccess: (() -&gt; Void)?) async -&gt; LocalizedError? {<br>        guard let request else { return AuthError.requestError }<br>        guard let model: RegisterModel = request.data.decode() else { return AuthError.decodeError }<br>        guard model.username.isEmpty == false else { return AuthError.emptyUsername }<br>        onSuccess?()<br><br>        let result: FirebaseResponse&lt;UsernameCheckModel&gt; = await FirestoreManager.shared.request(request)<br>        if result.status == .error(5) &amp;&amp; result.content == nil {<br>            return await nextHandler?.handle(nil)<br>        }<br><br>        return AuthError.usernameAlreadyUsed<br>    }<br>}</pre><p>Let’s look at what this code does.</p><ul><li>Even if the Handler method does not expect a request, this chain needs a request. So our first check is whether the request exists.</li><li>Afterward, we check whether the model is correct in our request. This way, we know that the content of the request we send will be correct, and if we need it (which we do), we can perform validations on the request body.</li><li>We want to check the username. So, isn’t it necessary to get a username? Let’s check this.</li><li>Then we see a closure called onSuccess. So what is this? I needed to be able to say “The previous transaction was successful, do this before you do your own thing” when triggering the previous chain or the chain itself. Therefore, such a closure was born entirely out of my need.</li><li>Afterward, we go to a service and wait for a response from Firebase. The logic behind the code here is as follows. If no document is found, error number 5 is returned. This is exactly what we want!</li><li>If there is no data, we can write our usage in the next step. That’s why we trigger nextHandler’s handle method.</li><li>Of course, if we did not come to such a conclusion, the username unfortunately does not exist and we return the relevant error to inform our user of this.</li></ul><p>Then we can move on to our next step. The next handler of our first chain: <strong>AuthHandler.</strong></p><pre>final class AuthHandler&lt;T: FirebaseAuthRequestStrategy&gt;: SociaHandler {<br>    typealias Request = T<br><br>    var nextHandler: (any SociaHandler)?<br>    var request: T?<br>    <br>    init(with handler: (any SociaHandler)?) {<br>        nextHandler = handler<br>    }<br>    <br>    func handle(_ onSuccess: (() -&gt; Void)?) async -&gt; LocalizedError? {<br>        guard let request else { return AuthError.requestError }<br>        guard let model: RegisterModel = request.data.decode() else { return AuthError.decodeError }<br>        guard model.email.isEmpty == false else { return AuthError.emptyEmail }<br>        guard model.password.isEmpty == false else { return AuthError.emptyPassword }<br>        guard model.rePassword.isEmpty == false else { return AuthError.emptyRepassword }<br>        guard (model.password.count &gt; 8) == false else { return AuthError.passwordTooShort }<br>        guard model.password == model.rePassword else { return AuthError.passwordsNotMatched }<br>        onSuccess?()<br><br>        let result = await FirebaseAuthManager.shared.request(request)<br>        if result.status == .success {<br>            return await nextHandler?.handle(nil)<br>        }<br>        <br>        return AuthError.emailAlreadyUsed<br>    }<br>}</pre><p>Let’s examine the differences from our first chain.</p><ul><li>Everything is the same, right down to model checking. We need more validation. We can increase or decrease the number here according to our needs.</li><li>Then we make a different service call and register the user. If the registration is successful, the image upload chain begins for us.</li></ul><pre>final class ProfilePhotoHandler&lt;T: FirestorageRequestStrategy&gt;: SociaHandler {<br>    typealias Request = T<br><br>    var nextHandler: (any SociaHandler)?<br>    var request: T?<br>    <br>    init(with handler: (any SociaHandler)?) {<br>        nextHandler = handler<br>    }<br>    <br>    func handle(_ onSuccess: (() -&gt; Void)?) async -&gt; LocalizedError? {<br>        guard let request else { return AuthError.requestError }<br>        guard request.storageData.isEmpty == false else { return await nextHandler?.handle(nil) }<br>        onSuccess?()<br><br>        let result: FirebaseResponse&lt;String&gt; = await FirestorageManagerManager.shared.request(request)<br>        if result.status == .success, let downloadLink = result.content {<br>            return await nextHandler?.handle { [weak self] in<br>                guard let handler = self?.nextHandler as? RegisterHandler&lt;RegisterRequest&gt; else { return }<br>                guard var requestModel = handler.request?.model else { return }<br>                requestModel.imagePath = downloadLink<br>                handler.request?.model = requestModel<br>            }<br>        }<br><br>        return AuthError.uploadError<br>    }<br>}</pre><p>This part is quite different. Because we have a different bond with the next chain.</p><ul><li>The main task of this chain is to upload the profile photo and bring us the download link.</li><li>But we will register our user in the next chain and we also need the link to the user’s profile picture. Therefore, when this chain is completed successfully, we attach the link we have to the request of the other chain.</li></ul><pre>final class RegisterHandler&lt;T: FirestoreRequestStrategy&gt;: SociaHandler {<br>    typealias Request = T<br><br>    var nextHandler: (any SociaHandler)?<br>    var request: T?<br>    <br>    init(with handler: (any SociaHandler)?) {<br>        nextHandler = handler<br>    }<br>    <br>    func handle(_ onSuccess: (() -&gt; Void)?) async -&gt; LocalizedError? {<br>        guard let request else { return AuthError.requestError }<br>        guard let model: UserModel = request.data.decode() else { return AuthError.decodeError }<br>        guard model.name?.isEmpty == false else { return AuthError.emptyName }<br>        guard model.surname?.isEmpty == false else { return AuthError.emptySurname }<br>        guard (model.bio?.count ?? 0 &lt; 250) == true else { return AuthError.bioTooLong }<br>        onSuccess?()<br><br>        let result: FirebaseResponse&lt;UserModel&gt; = await FirestoreManager.shared.request(request)<br>        if result.status == .success {<br>            return await nextHandler?.handle(nil)<br>        }<br><br>        return AuthError.uploadError<br>    }<br>}</pre><ul><li>onSuccess in our new chain now makes sense. The URL of the uploaded image is now included in the model we have. And with this step, the chain is completed.</li></ul><p>Now that we’ve written down all the relevant parts, let’s see how to connect them. I created all the models we needed. The basic thing when creating the chain is to start from the end.</p><pre>struct ChainTest: View {<br>    @State private var isAlertOn = false<br>    @State private var chainResult: LocalizedError?<br>    @State private var isLoadingOn = false<br>    @State private var isSheetOn = false<br>    <br>    var body: some View {<br>        ZStack {<br>            VStack {<br>                Button(&quot;Run Chain&quot;, action: runChain)<br>            }.confirmationDialog(&quot;Error!&quot;, isPresented: $isAlertOn, titleVisibility: .visible) {<br>                Button(&quot;Try Again!&quot;, action: runChain)<br>            } message: {<br>                Text(chainResult?.localizedDescription ?? &quot;&quot;)<br>            }.tint(.accentColor)<br>            <br>            if isLoadingOn {<br>                VStack {<br>                    ProgressView()<br>                }.frame(width: 100.0.responsiveW, height: 100.0.responsiveH)<br>                    .background(.ultraThinMaterial)<br>            }<br>        }.sheet(isPresented: $isSheetOn) {<br>            VStack {<br>                Image(systemName: &quot;checkmark.rectangle.stack.fill&quot;)<br>                    .font(.largeTitle)<br>                Text(&quot;Successful!&quot;)<br>            }<br>           <br>        }<br>    }<br>    <br>    private func runChain() {<br>        let registerModel = RegisterModel(username: &quot;ates&quot;, email: &quot;test1@gmail.com&quot;, password: &quot;12345678&quot;, rePassword: &quot;12345678&quot;)<br>        let userModel = UserModel(username: &quot;ates&quot;, name: &quot;Mehmet&quot;, surname: &quot;Ateş&quot;)<br>        let imageData = UIImage(systemName: &quot;applelogo&quot;)?.jpegData(compressionQuality: 0.8) ?? Data()<br>        <br>        let registerHandler = RegisterHandler&lt;RegisterRequest&gt;(with: nil)<br>        registerHandler.request = RegisterRequest(userModel)<br>        <br>        let profilePhotoHandler = ProfilePhotoHandler&lt;UploadProfilePhotoRequest&gt;(with: registerHandler)<br>        profilePhotoHandler.request = UploadProfilePhotoRequest(username: &quot;ates&quot;, storageData: imageData)<br>        <br>        let authHandler = AuthHandler&lt;AuthRequest&gt;(with: profilePhotoHandler)<br>        authHandler.request = AuthRequest(registerModel)<br>        <br>        let checkUsernameHandler = CheckUsernameHandler&lt;CheckUsernameRequest&gt;(with: authHandler)<br>        checkUsernameHandler.request = CheckUsernameRequest(registerModel)<br>        <br>        Task {<br>            isLoadingOn = true<br>            chainResult = await checkUsernameHandler.handle(nil)<br>            guard chainResult != nil else { return isLoadingOn = false }<br>            isAlertOn.toggle()<br>            isLoadingOn = false<br>        }<br>    }<br>}</pre><p>On the page I created above, our first attempt was successful. Because all validations are smooth and our user registration is open.</p><p>But on our second try, exactly what we expected happened. We’ve just created a registration! You cannot use the same username.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*yH7N9vrYdrT7KOrvbL0y5w.png" /></figure><p>To do this, I updated the username, run the project again, and try again. But I forgot one thing. My email is the same and I just created a user with it.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*NnAJjCQXoqIe5KUEjzZVDw.png" /></figure><p>I change this and try again. This time, I see a screen like this.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*lScr0rOfYuo2C2KkF6rxxg.png" /></figure><p>We have comprehensively examined the Chain of Responsibility and seen what difference it makes in real projects.</p><ul><li><strong>Our code is now definitely fragmented and open to development.</strong></li><li><strong>It’s easy to add a flow in between, at the beginning, or the end.</strong></li><li><strong>It is very easy to update the relevant chain and catch which chain an error occurs in.</strong></li><li><strong>Testability is high.</strong></li></ul><h3>Summary</h3><p>We examined the Chain Of Responsibility and managed to perform a string operation in a chain. Now, when I want to add a new piece to Socia’s recording flow, I can create a handler and quickly add it to any position I want in the chain.</p><p>Thank you for reading. Happy Swifting.</p><h3>You should definitely check this out.</h3><p><a href="https://medium.com/@dev.mehmetates/why-did-i-code-like-this-656bcd089086">Why did I code like this?</a></p><h3>My Resources</h3><ul><li>HolySwift — <a href="https://holyswift.app/chain-of-responsibility-pattern-in-swift/">Chain Of Responsibility</a></li><li>Refactoring.Guru — <a href="https://refactoring.guru/design-patterns/chain-of-responsibility">Chain Of Responsibility Article</a> — <a href="https://refactoring.guru/design-patterns/chain-of-responsibility/swift/example#example-1">Example Code</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=11fc0a0f9ec2" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[What is Swift Package Manager?]]></title>
            <link>https://medium.com/@dev.mehmetates/what-is-swift-package-manager-5b64dd70686e?source=rss-393f090c04a------2</link>
            <guid isPermaLink="false">https://medium.com/p/5b64dd70686e</guid>
            <category><![CDATA[swift-package-manager]]></category>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[swift]]></category>
            <dc:creator><![CDATA[Mehmet Ateş]]></dc:creator>
            <pubDate>Sat, 25 Mar 2023 11:32:01 GMT</pubDate>
            <atom:updated>2023-03-25T11:32:01.517Z</atom:updated>
            <content:encoded><![CDATA[<p>Swift is a great programming language that we use in our lives. However, as in other languages, it has ready-made templates and packages. So what is this SPM, what does it do?</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/1*JooWw3CCko4h3jczpiNmpA.png" /></figure><p>A manager that allows us to manage, write and publish Swift packages in our project. First of all, let’s talk about what we were doing before SPM, then let’s learn how to use it and what it can add to our lives.</p><p>SPM is a relatively new technology. For this reason, we were meeting this need with a tool called <strong>CocoaPods</strong>, which was used before instead of <strong>SPM</strong>. CocoaPods brought us a lot of things,</p><ul><li>Having to work on .xcworkspace</li><li>Enormous pods folder</li><li>A Podfile in ruby ​​language</li><li>A Podfile.lock file that changes every time it is fetch</li></ul><p>and it really wasn’t very good. Let us explain this to you with a real example.</p><p>Previously, I was managing many external package dependencies such as Firebase to Socia, one of its very big projects, with Cocoa Pods. And my project had all the files I listed above. And when I met spm and saw that all of its packages were suitable for spm, I decided to make this transition. Below is a commit that shows the changes I made. You can decide 🙂</p><p><a href="https://github.com/devmehmetates/Socia/commit/de909f8ab6f333abce3b11beb24364b32872e362">socia now managed with spm · devmehmetates/Socia@de909f8</a></p><p>My switch to spme has been a huge relief and an incredible reduction in the repo size of my project. Yes <strong>CocoaPods is still a good solution</strong> you might need. <strong>But if you don’t need it, you have to choose SPM.</strong></p><p>Now we can learn to use SPM and how to write a Swift package. It’s absolutely incredibly easy on those two counts. Trust me 🔨</p><p>Your current packages look like below on xcode. From here you can add packages, delete packages, that is, you can fully manage your packages.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*M6k8t908KmoVBbx7zOVdOg.png" /></figure><p><strong>To delete a package</strong>, simply click on your package and press the “-” icon.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*S7I0dOdCan9RYGZhuOJM2Q.png" /><figcaption>Click “-” button</figcaption></figure><p><strong>To add it</strong>, you need to press the + key in the same way, then call a package prepared with a url.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*UgxKe2gjkRJqE8FeRp7fTQ.png" /><figcaption>Click “+” button</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*UQkevoAJ35DDSoYs6wrq4w.png" /><figcaption>Paste Package url and click “Add Package” button</figcaption></figure><p>That’s how easy it is to add a Swift package to your project. Then you can import the package and use it as you want in your project. Now let’s get to the fun part. Let’s create an Swift package :)</p><p>Open Xcode and select Swift Package option below.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*t4RyXhddHqW87Sp8ug1qbg.png" /></figure><p>Afterwards, we make the developments related to our package under the source folder in the project that is opened.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*t0HJ8sfv77tg4qKAZj2xGA.png" /></figure><p>Then we publish our package on a platform such as github. In this way, our package can now be used by both other people and ourselves.</p><blockquote>If the package repository is private, only users with package access via Xcode can use the package.</blockquote><p><a href="https://github.com/devmehmetates/StickyAsyncImageSwiftUI">GitHub - devmehmetates/StickyAsyncImageSwiftUI</a></p><h4><strong>Result</strong></h4><p>In this article we learned how to get rid of CocoaPods using SPM and what it gives us, How we can use it in our Swift packages project and how to create a package. This is a really simple but effective topic. 😍</p><p>Thanks For Reading 👀</p><h4>Good Swift Packages</h4><ul><li><a href="https://github.com/apple/swift-algorithms.git">Swift Algorithms</a> 🧡, I highly recommend checking out this package.</li><li><a href="https://github.com/roberthein/TinyConstraints.git">Tiny Constraints</a></li><li><a href="https://github.com/Alamofire/Alamofire.git">Alamofire</a></li><li><a href="https://github.com/SnapKit/SnapKit.git">SnapKit</a></li><li><a href="https://github.com/onevcat/Kingfisher.git">KingFisher</a></li><li><a href="https://github.com/firebase/firebase-ios-sdk.git">Firebase</a>, also <a href="https://medium.com/swift-productions/how-to-add-firebase-with-spm-swiftui-d083189d510d">this article</a> can help for this issue.</li><li><a href="https://github.com/Trendyol/ios-components.git">Trendyol iOS Components</a></li><li><a href="https://github.com/airbnb/lottie-ios.git">Lottie</a></li><li><a href="https://github.com/SwiftyJSON/SwiftyJSON">SwiftyJSON</a></li><li><a href="https://github.com/Juanpe/SkeletonView.git">Skeleton View</a></li></ul><h4>Resources</h4><p><a href="https://www.swift.org/package-manager/">Swift Package Manager</a> by Swift.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=5b64dd70686e" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Builder Pattern in Swift]]></title>
            <link>https://medium.com/ibtech/builder-pattern-in-swift-e712cc5d7bbc?source=rss-393f090c04a------2</link>
            <guid isPermaLink="false">https://medium.com/p/e712cc5d7bbc</guid>
            <category><![CDATA[sustainability]]></category>
            <category><![CDATA[design-pattern-ios]]></category>
            <category><![CDATA[swift]]></category>
            <dc:creator><![CDATA[Mehmet Ateş]]></dc:creator>
            <pubDate>Sat, 18 Mar 2023 10:37:48 GMT</pubDate>
            <atom:updated>2023-03-20T08:02:45.002Z</atom:updated>
            <content:encoded><![CDATA[<p>Greetings again. Our topic today is not about learning how to do something, but about doing something better. As you know, design patterns do not allow us to do anything, but to write more sustainable projects and make the project manageable. So let’s start the review. 👀</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/1*6XMqBnwIxeUxyqpADz8z-A.png" /></figure><p>First of all, let’s look at what the builder pattern is and what it does for us. Creating simple objects is easy. For example, let’s consider a user object with only one property. 📖</p><pre>// Defination<br>final class User: Identifiable {<br>    var username: UUID<br>    <br>    init(username: UUID) {<br>        self.username = username<br>    }<br>}<br><br><br>// Example Usage<br>User(username: UUID())</pre><p>As you can see, we can create and use it quite simply. What if this class was a car object and branched out to its subclasses?</p><pre>// Definations<br>final class Car {<br>    var engine: Engine<br>    var wheels: [Wheel]<br>    var body: Body<br><br>    init(engine: Engine, wheels: [Wheel], body: Body) {<br>        self.engine = engine<br>        self.wheels = wheels<br>        self.body = body<br>    }<br>}<br><br>final class Engine {<br>    var horsepower: Int<br>    var cylinderCount: Int<br><br>    init(horsepower: Int, cylinderCount: Int) {<br>        self.horsepower = horsepower<br>        self.cylinderCount = cylinderCount<br>    }<br>}<br><br>final class Wheel {<br>    var size: Int<br>    var type: String<br><br>    init(size: Int, type: String) {<br>        self.size = size<br>        self.type = type<br>    }<br>}<br><br>final class Body {<br>    var color: String<br>    var type: String<br><br>    init(color: String, type: String) {<br>        self.color = color<br>        self.type = type<br>    }<br>}<br><br>// Example Usage<br>Car(engine: .init(horsepower: 100, cylinderCount: 4),<br>    wheels: [.init(size: 20, type: &quot;Low Profile&quot;),<br>             .init(size: 20, type: &quot;Low Profile&quot;),<br>             .init(size: 20, type: &quot;Low Profile&quot;),<br>             .init(size: 20, type: &quot;Low Profile&quot;)],<br>    body: .init(color: &quot;red&quot;, type: &quot;Sport&quot;)<br>)</pre><p>You can see that things are getting more and more complicated. And this is a situation that unfortunately reduces legibility and reduces maintainability after a while. And also remember, you have to reflect these properties in the constructor anyway. What about the Builder Pattern? What if we used the Builder Pattern. What would we gain?💪🏼</p><ul><li>By separating the object creation steps, it makes the object creation process more understandable and readable.</li><li>It facilitates the creation of objects with different properties. Builder classes provide customized build methods for a particular object type, so you can easily build objects with different properties.</li><li>It makes the object creation process more modular. The Builder interface separates the object creation steps into smaller and more manageable parts. In this way, you can customize the object creation process as you wish and have the option to add or remove different steps.</li><li>Provides flexibility in the object creation process. With the Builder design pattern, you can make the object creation process more flexible.</li><li>Using different Builder classes, you can create objects with different properties and customize the object creation process the way you want.</li><li>Increases code reusability. The Builder design pattern uses the same interface for building different objects. In this way, it increases the reusability of the code and prevents unnecessary code duplication.</li></ul><p>So what are we waiting for? Let’s do this. When we look at the object, our vehicle is waiting for the engine, wheels and a body from us. With the Builder pattern, we can provide them flexibly.</p><pre>protocol CarBuilderProtocol {<br>    func setEngine(horsepower: Int, cylinderCount: Int) -&gt; CarBuilderProtocol<br>    func setWheel(size: Int, type: String) -&gt; CarBuilderProtocol<br>    func setBody(color: String, type: String) -&gt; CarBuilderProtocol<br>    func build() -&gt; Car<br>}<br><br>final class CarBuilder: CarBuilderProtocol {<br>    var engine: Engine?<br>    var wheels: [Wheel] = []<br>    var body: Body?<br><br>    @discardableResult<br>    func setEngine(horsepower: Int, cylinderCount: Int) -&gt; CarBuilderProtocol {<br>        engine = Engine(horsepower: horsepower, cylinderCount: cylinderCount)<br>        return self<br>    }<br><br>    @discardableResult<br>    func setWheel(size: Int, type: String) -&gt; CarBuilderProtocol {<br>        wheels.append(Wheel(size: size, type: type))<br>        return self<br>    }<br><br>    @discardableResult<br>    func setBody(color: String, type: String) -&gt; CarBuilderProtocol {<br>        body = Body(color: color, type: type)<br>        return self<br>    }<br><br>    func build() -&gt; Car {<br>        return Car(engine: engine ?? Engine(horsepower: 0, cylinderCount: 0), wheels: wheels, body: body ?? Body(color: &quot;Undefined&quot;, type: &quot;Undefined&quot;))<br>    }<br>}</pre><blockquote>No protocol is required here, but since Swift is a P.O.P language, I chose to write it this way.</blockquote><p>What has changed now? Now we are generating car objects through the builder object. This gives us tremendous flexibility for every feature. Like what, let’s see.</p><pre>// The car object can now be created without any attributes.<br>CarBuilder()<br>    .build()<br>// Can only be created by giving the engine.<br>CarBuilder()<br>    .setEngine(horsepower: 400, cylinderCount: 8)<br>    .build()<br>// It can also be created by just giving the body.<br>CarBuilder()<br>    .setBody(color: &quot;Black&quot;, type: &quot;SUV&quot;)<br>    .build()<br>// Or you can set all the features.<br>CarBuilder()<br>    .setEngine(horsepower: 300, cylinderCount: 6)<br>    .setBody(color: &quot;Black&quot;, type: &quot;SUV&quot;)<br>    .setWheel(size: 22, type: &quot;Off-Road&quot;)<br>    .setWheel(size: 22, type: &quot;Off-Road&quot;)<br>    .setWheel(size: 22, type: &quot;Off-Road&quot;)<br>    .setWheel(size: 22, type: &quot;Off-Road&quot;)<br>    .build()</pre><p>So how much can we improve? We have ready-made cars and do we want to use them? How about a director class, for example.🌞</p><pre>final class CarDirector {<br>    var builder: CarBuilderProtocol<br><br>    init(builder: CarBuilderProtocol) {<br>        self.builder = builder<br>    }<br><br>    func constructSportsCar() -&gt; Car {<br>        return builder.setEngine(horsepower: 400, cylinderCount: 8)<br>            .setWheel(size: 19, type: &quot;Low Profile&quot;)<br>            .setWheel(size: 19, type: &quot;Low Profile&quot;)<br>            .setWheel(size: 19, type: &quot;Low Profile&quot;)<br>            .setWheel(size: 19, type: &quot;Low Profile&quot;)<br>            .setBody(color: &quot;Red&quot;, type: &quot;Sports&quot;)<br>            .build()<br>    }<br><br>    func constructSUV() -&gt; Car {<br>        return builder.setEngine(horsepower: 300, cylinderCount: 6)<br>            .setWheel(size: 22, type: &quot;Off-Road&quot;)<br>            .setWheel(size: 22, type: &quot;Off-Road&quot;)<br>            .setWheel(size: 22, type: &quot;Off-Road&quot;)<br>            .setWheel(size: 22, type: &quot;Off-Road&quot;)<br>            .setBody(color: &quot;Black&quot;, type: &quot;SUV&quot;)<br>            .build()<br>    }<br>}</pre><p>The Director class is fed with an imported builder class. Thus, any builder with the appropriate protocol can be used. For example, our builder is constantly adding wheels. Instead, we can create a controlled builder and update the setWhell function by adding the wheel if the number of wheels is 4 or less. And that works perfectly in our director class 🤩</p><p>Our job becomes easier when we also prepare our ready-made templates using Director. For example, you can connect it to a service and easily create objects that you use all the time. 😎</p><pre>// Returns a suv car for us.<br>CarDirector(builder: CarBuilder())<br>    .constructSUV()<br><br>// Returns a sports car for us.<br>CarDirector(builder: CarBuilder())<br>    .constructSportsCar()</pre><h4>Result</h4><p>The Builder pattern, like any busy but beautiful thing, may not be desirable in the first place and may not make a spectacular change instantly. However, it provides great flexibility and strong manageability in a long-term project.</p><p>Happy coding everyone. With Swift of course. 🧡</p><h4>Resources</h4><ul><li>Builder Pattern By <a href="https://www.swiftbysundell.com/articles/using-the-builder-pattern-in-swift/"><strong>Swiftbysundell</strong></a></li></ul><h4>Also</h4><p>Thanks also to <a href="https://www.linkedin.com/in/sonmezvolkan/">Volkan Sönmez</a>, who informed and supported me about the subject.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e712cc5d7bbc" width="1" height="1" alt=""><hr><p><a href="https://medium.com/ibtech/builder-pattern-in-swift-e712cc5d7bbc">Builder Pattern in Swift</a> was originally published in <a href="https://medium.com/ibtech">IBTech</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[HealthKit Basics in Swift]]></title>
            <link>https://medium.com/ibtech/healthkit-basics-in-swift-30ea6ce27a78?source=rss-393f090c04a------2</link>
            <guid isPermaLink="false">https://medium.com/p/30ea6ce27a78</guid>
            <category><![CDATA[uikit]]></category>
            <category><![CDATA[healthkit]]></category>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[swiftui]]></category>
            <dc:creator><![CDATA[Mehmet Ateş]]></dc:creator>
            <pubDate>Sat, 11 Mar 2023 12:03:44 GMT</pubDate>
            <atom:updated>2023-03-13T04:19:54.811Z</atom:updated>
            <content:encoded><![CDATA[<p>Greetings again everyone. After a short break, it is back with a fun article.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/1*Ca2Wxa7sbF--D6wJO-3WSQ.png" /></figure><p>Health problems are very popular nowadays. And developing technologies are trying to support us in this regard. Apple has also not left its ecosystem incomplete in this regard. With the module called HealthKit they have developed, we can use the sensors on the iPhone — iWatch and make health assessments. Let’s learn the basics of this kit.</p><p>Before we begin, we have a topic about personal data security, which is one of the things Apple does best. We need to get permission from the user by stating that we need some data.</p><p>There are a few simple steps you need to take to do this. After that, everything is very easy.</p><p>The first step is to add healthkit under the Signing &amp; Capabilities menu.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*7Up-FjaxxKqRNtCB5Ecc4w.png" /></figure><p>Then adding these 3 values ​​to the info plist and giving your message to the user.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*l38FxvvaU9ZW3IuWizASQw.png" /></figure><p>After that it ends in code. We get this screen with the code block below.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*kTItQhpjbgIpoDfNWoFDRQ.png" /></figure><pre>struct HealthKitView: View {<br>    var healthStore: HKHealthStore = HKHealthStore()<br>    <br>    init() {<br>        request()<br>    }<br>    <br>    private func request() {<br>        let typesToRead: Set&lt;HKObjectType&gt; = [HKObjectType.quantityType(forIdentifier: .stepCount)!, HKObjectType.quantityType(forIdentifier: .distanceWalkingRunning)!, HKObjectType.quantityType(forIdentifier: .heartRate)!]<br><br>        let typesToWrite: Set&lt;HKSampleType&gt; = [HKObjectType.quantityType(forIdentifier: .stepCount)!, HKObjectType.quantityType(forIdentifier: .distanceWalkingRunning)!]<br>        <br>        healthStore.requestAuthorization(toShare: typesToWrite, read: typesToRead) { (success, error) in<br>            if success {<br>               // Success<br>            } else {<br>                // Error handle<br>            }<br>        }<br>    }<br>}</pre><p>We got our permissions. Now let’s explore some of the healthKit capabilities.</p><ul><li>Tracking Physical Activity</li></ul><p>One of the most popular uses for HealthKit is tracking physical activity. HealthKit can monitor your steps, distance, and even your workouts. This data can be used to help you set goals and track your progress. You can also use third-party apps, such as MyFitnessPal or Strava, to track your workouts and sync the data with HealthKit.</p><p>For example, let’s read the step count data;</p><pre>let stepsCount = HKQuantityType.quantityType(forIdentifier: .stepCount)!<br>let startDate = Calendar.current.date(byAdding: .day, value: -7, to: Date())<br>let predicate = HKQuery.predicateForSamples(withStart: startDate, end: Date(), options: .strictStartDate)<br><br>let query = HKSampleQuery(sampleType: stepsCount, predicate: predicate, limit: Int(HKObjectQueryNoLimit), sortDescriptors: nil) { (query, results, error) in<br>    guard let samples = results as? [HKQuantitySample] else {<br>        return<br>    }<br>    <br>    let totalSteps = samples.reduce(0, {$0 + $1.quantity.doubleValue(for: HKUnit.count())})<br>    print(&quot;Last 7 days step count: \(totalSteps)&quot;)<br>}<br>healthStore.execute(query)</pre><ul><li>Monitoring Vital Signs</li></ul><p>HealthKit can also be used to monitor vital signs, such as your heart rate and blood pressure. With the help of third-party devices, such as blood pressure monitors or heart rate monitors, you can easily track this data and share it with your doctor or other healthcare professionals.</p><p>For example, let’s write a screen that prints your beautiful heartbeats on the screen;</p><pre>import UIKit<br>import HealthKit<br><br>class ViewController: UIViewController {<br>    <br>    let healthStore = HKHealthStore()<br>    var heartRateQuery: HKObserverQuery?<br>    <br>    @IBOutlet weak var heartRateLabel: UILabel!<br>    <br>    override func viewDidLoad() {<br>        super.viewDidLoad()<br>        <br>        // Check if HealthKit is available on this device<br>        guard HKHealthStore.isHealthDataAvailable() else {<br>            print(&quot;HealthKit is not available on this device&quot;)<br>            return<br>        }<br>        <br>        // Set the types of data we want to read from HealthKit<br>        let readDataTypes: Set&lt;HKObjectType&gt; = [<br>            HKObjectType.quantityType(forIdentifier: .heartRate)!<br>        ]<br>        <br>        // Request authorization to read the data types<br>        healthStore.requestAuthorization(toShare: nil, read: readDataTypes) { (success, error) in<br>            if let error = error {<br>                print(&quot;Error requesting authorization: \(error.localizedDescription)&quot;)<br>                return<br>            }<br>            <br>            // Start the heart rate observer query<br>            self.startHeartRateObserverQuery()<br>        }<br>    }<br>    <br>    func startHeartRateObserverQuery() {<br>        // Set up the heart rate observer query<br>        let heartRateType = HKObjectType.quantityType(forIdentifier: .heartRate)!<br>        heartRateQuery = HKObserverQuery(sampleType: heartRateType, predicate: nil) { (query, completionHandler, error) in<br>            if let error = error {<br>                print(&quot;Error: \(error.localizedDescription)&quot;)<br>                return<br>            }<br>            <br>            // Get the most recent heart rate sample<br>            let sortDescriptor = NSSortDescriptor(key: HKSampleSortIdentifierStartDate, ascending: false)<br>            let heartRateSampleQuery = HKSampleQuery(sampleType: heartRateType, predicate: nil, limit: 1, sortDescriptors: [sortDescriptor]) { (query, samples, error) in<br>                if let error = error {<br>                    print(&quot;Error: \(error.localizedDescription)&quot;)<br>                    return<br>                }<br>                <br>                // Update the UI with the heart rate value<br>                if let heartRateSample = samples?.first as? HKQuantitySample {<br>                    let heartRateUnit = HKUnit.count().unitDivided(by: HKUnit.minute())<br>                    let heartRate = Int(heartRateSample.quantity.doubleValue(for: heartRateUnit))<br>                    DispatchQueue.main.async {<br>                        self.heartRateLabel.text = &quot;\(heartRate) bpm&quot;<br>                    }<br>                }<br>            }<br>            <br>            // Execute the heart rate sample query<br>            self.healthStore.execute(heartRateSampleQuery)<br>            <br>            // Call the completion handler<br>            completionHandler()<br>        }<br>        <br>        // Add the heart rate observer query to the health store<br>        healthStore.execute(heartRateQuery!)<br>    }<br>    <br>    deinit {<br>        // Stop the heart rate observer query<br>        healthStore.stop(heartRateQuery!)<br>    }<br>    <br>}</pre><ul><li>Monitoring Sleep</li></ul><p>Getting enough sleep is essential for good health, and HealthKit can help you track your sleep patterns. You can monitor how long you sleep each night, the quality of your sleep, and even your bedtime routine. This data can help you identify areas where you need to improve your sleep habits.</p><p>You can choose to track your sleep and keep the nights a little shorter :)</p><pre>import HealthKit<br><br>let healthStore = HKHealthStore()<br><br>// Request authorization to access sleep data<br>let sleepType = HKObjectType.categoryType(forIdentifier: HKCategoryTypeIdentifier.sleepAnalysis)!<br>healthStore.requestAuthorization(toShare: nil, read: [sleepType]) { (success, error) in<br>    if success {<br>        // Query for sleep data<br>        let sortDescriptor = NSSortDescriptor(key: HKSampleSortIdentifierEndDate, ascending: false)<br>        let query = HKSampleQuery(sampleType: sleepType, predicate: nil, limit: 30, sortDescriptors: [sortDescriptor]) { (query, samples, error) in<br>            guard let samples = samples as? [HKCategorySample], error == nil else {<br>                print(&quot;Failed to fetch sleep data: \(error!.localizedDescription)&quot;)<br>                return<br>            }<br>            for sample in samples {<br>                let startDate = sample.startDate<br>                let endDate = sample.endDate<br>                print(&quot;Sleep start: \(startDate), end: \(endDate)&quot;)<br>            }<br>        }<br>        healthStore.execute(query)<br>    } else {<br>        print(&quot;Authorization to access sleep data was denied.&quot;)<br>    }<br>}</pre><p>In conclusion, HealthKit is a powerful tool that can help you take control of your health and wellbeing. Whether you want to monitor your daily activity, track your vital signs, manage your medications, or monitor your sleep, HealthKit has you covered. With its user-friendly interface and seamless integration with third-party devices, HealthKit makes it easy to stay on top of your health goals. So why not give it a try and see how it can improve your life? Remember, your health is your wealth, and HealthKit is here to help you achieve it.</p><p>Have a healthy weekend everyone ❤</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=30ea6ce27a78" width="1" height="1" alt=""><hr><p><a href="https://medium.com/ibtech/healthkit-basics-in-swift-30ea6ce27a78">HealthKit Basics in Swift</a> was originally published in <a href="https://medium.com/ibtech">IBTech</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[SwiftUI Basics for UIKit Developers]]></title>
            <link>https://medium.com/ibtech/swiftui-basics-for-uikit-developers-a141c9061635?source=rss-393f090c04a------2</link>
            <guid isPermaLink="false">https://medium.com/p/a141c9061635</guid>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[uikit]]></category>
            <category><![CDATA[declarative-programming]]></category>
            <category><![CDATA[swiftui]]></category>
            <category><![CDATA[new-techonology]]></category>
            <dc:creator><![CDATA[Mehmet Ateş]]></dc:creator>
            <pubDate>Sat, 14 Jan 2023 19:51:23 GMT</pubDate>
            <atom:updated>2023-01-16T06:38:46.763Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/700/1*HQO9ktkwIEMxHAknb2-swg.png" /></figure><p>Hello everybody. I’m trying to get back to the articles after a little break. Today I’m going to talk to you about how we can transition to a framework that I love and that I think will have a big share in the future of iOS development.</p><p>One framework I’m talking about is, of course, <strong>SwiftUI</strong>. With the development speed of today’s technologies and the increasing iOS deployment targets, SwiftUI is becoming more accessible for us developers every day. But how ready are we for it? It’s good to stay up to date, so let’s get started.</p><h3>Components</h3><p>SwiftUI has its own unique components. In cases where it is insufficient, it allows the use of UIKit and provides a complete result. As an example, we can give the most basic component <strong>LABEL</strong> as an example.</p><ul><li>In UIKit, a red label is defined as follows;</li></ul><pre>let label = UILabel()<br>label.text = &quot;Center&quot;<br>label.textColor = .red</pre><ul><li>In SwiftUI, that’s all.</li></ul><pre>Text(&quot;Center&quot;)<br>    .foregroundColor(.red)</pre><h3>Configuration</h3><ul><li>UIKit components are classes. And there are properties belonging to classes. As seen below, it has many variables such as label, text, text Color, font etc.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*sDjcxKOya2rK9-oeYQ5uDg.png" /></figure><ul><li>You can’t see this in SwiftUI. Because SwiftUI manages them through modifiers. Each view is wrapped in modifiers when it receives its properties such as foregroundColor. You can think of it as having a “Modified Text” object.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Qx7YVdhX4yx4K3NJYrQWgA.png" /></figure><p>So in summary when configuring classes in UIKit. We modify structures in SwiftUI.</p><pre>label.textColor = .red // It&#39;s still the label class.<br><br>Text(&quot;Text&quot;) // It&#39;s now a modified struct.<br>  .foregroundColor(.red) </pre><h3>Reactive Programming</h3><p>It contains the basic elements of SwiftUI Combine and with it reactive programming features. Combine can also be used with UIKit, but we generally do not see its use since iOS 13 requires a deployment target. This is one of the advantages of SwiftUI. Let’s try something using a common view model.</p><pre>import Combine<br>import Foundation<br><br>final class ViewModel: ObservableObject {<br>    @Published var text: String = &quot;Some Text&quot;<br>    <br>    init() {<br>        DispatchQueue.main.asyncAfter(deadline: .now() + 3) { [weak self] in<br>            self?.text = &quot;Some text after 3 second&quot;<br>        }<br>    }<br>}</pre><ul><li>You can do a very simple bind operation in UIKit as follows.</li></ul><pre>import Combine<br>import UIKit<br><br>final class UIKitLayoutViewController: UIViewController {<br>    @IBOutlet var mainLabel: UILabel!<br>    @ObservedObject private var viewModel = ViewModel()<br>    private var subscriptions = Set&lt;AnyCancellable&gt;()<br>    <br>    override func viewDidLoad() {<br>        super.viewDidLoad()<br>        viewModel.$text.sink { textValue in<br>            self.mainLabel.text = textValue.description<br>        }.store(in: &amp;subscriptions)<br>    }<br>}</pre><ul><li>The SwiftUI equivalent of this will be just that;</li></ul><pre>import SwiftUI<br><br>struct SwiftUILayout: View {<br>    @ObservedObject private var viewModel: ViewModel = ViewModel()<br>    <br>    var body: some View {<br>        Text(viewModel.text)<br>    }<br>}</pre><h3>Layout</h3><p>UIKit offers us 2 options for layout. We determine the placement of the objects on the screen by providing <strong>CONSTRAINTS</strong> from the code either via the Storyboard or programmatically. I will prefer the commonly used Storyboards in this article.</p><h4>How do I center a text?</h4><ul><li>On <strong>UIKit</strong> you add a text to the storyboard as seen below. You then give the text the CenterX, and CenterY constraints. Thus, the text is printed on the screen centered.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*XHQ7upeuSX5PO5aux4RKhQ.png" /></figure><ul><li>In <strong>SwiftUI</strong>, you just need to add a Text object.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*RDpkArami3RAKtkhjZkSjA.png" /></figure><h4>How can I place a text at the top right with 10 px space?</h4><ul><li>In UIKit, it will be enough to add top and trailing constraints to text and set top value to 0 and trailing value to 10.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*48_iwoPbKZ38OhLMBj1bNg.png" /></figure><ul><li><strong>In SwiftUI</strong>, on the other hand, we will need to use Stack structures. A Vstack and an HStack are defined and the desired location is determined with spacers. Then .padding is used to set 10px spacing.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ZNYJwGtdZ0dW1a-7nNjIag.png" /></figure><p>These are really easy cases. Let’s make this a little harder.</p><h4>How to create a view that lists 10 items on the screen, 4 of which are blue, 4 are red, and the remaining 2 are yellow?</h4><ul><li>The <strong>UIKit</strong> equivalent of this is a tableView. And to do that (we’re a little bit luckier if storyboard is used here) we need to write as much code as below.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*my2oaXTlMzYuJlz5-fTk4A.png" /></figure><ul><li>You should also create a cell in the storyboard and connect it to the viewController.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*UXZd1edmbL_-W65CicAOug.png" /></figure><ul><li>The SwiftUI counterpart, on the other hand, is really quite simple.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Zxjq1lyPfTeoSIH5pDZCvQ.png" /></figure><blockquote>Note: By the way, some people here might say: <strong>There is a Compositional Layout, why didn’t we use it?</strong></blockquote><blockquote>The event here is the deployment target that is blocking you. If this is going to be iOS 13 above, I think we would prefer to write SwiftUI for such simple structures.</blockquote><p>Thus, we have seen how there is a connection between SwiftUI and UIKit. This is how I will proceed by making comparisons, I’m thinking of making a series where we can see the positive and negative aspects of both SwiftUI and UIKit. I hope I can maintain this continuity.</p><p>Happy reading, Swift Full Coding 🧡.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a141c9061635" width="1" height="1" alt=""><hr><p><a href="https://medium.com/ibtech/swiftui-basics-for-uikit-developers-a141c9061635">SwiftUI Basics for UIKit Developers</a> was originally published in <a href="https://medium.com/ibtech">IBTech</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[iOS Developer Yolunda]]></title>
            <link>https://medium.com/@dev.mehmetates/ios-developer-yolunda-75b79ccc94fb?source=rss-393f090c04a------2</link>
            <guid isPermaLink="false">https://medium.com/p/75b79ccc94fb</guid>
            <dc:creator><![CDATA[Mehmet Ateş]]></dc:creator>
            <pubDate>Fri, 30 Dec 2022 20:16:34 GMT</pubDate>
            <atom:updated>2022-12-31T15:18:51.477Z</atom:updated>
            <content:encoded><![CDATA[<h3>iOS Developer Olma Yolunda 365 Gün</h3><p>Herkese selamlar. Umarım herkesin sağlığı ve keyfi yerindedir. Bugün sizlere geçen yıl atmış olduğum bu;</p><h3>Mehmet ATEŞ on Twitter: &quot;365 gün boyunca iOS kodlayarak 2022&#39;yi maksimum şekilde değerlendirme kararı aldım. Bu tweeti seri halinde devam ettirerek her gün yaptıklarımı paylaşacağım. Tam 1 sene sonra bu tweete bakıp ne diyeceğimi merak ediyorum :)Repo👇🏼https://t.co/VUGmAvGYyE / Twitter&quot;</h3><p>365 gün boyunca iOS kodlayarak 2022&#39;yi maksimum şekilde değerlendirme kararı aldım. Bu tweeti seri halinde devam ettirerek her gün yaptıklarımı paylaşacağım. Tam 1 sene sonra bu tweete bakıp ne diyeceğimi merak ediyorum :)Repo👇🏼https://t.co/VUGmAvGYyE</p><p>tweet ile başlamış olduğum 365 günlük bir challenge süresince neler yaşadığımı ve bunu nasıl başardığımı anlatmak istiyorum. O halde hadi gelin bu uzun maratonun başından sonuna neler oldu göz atalım 🌞</p><p>2021 Eylül ayından bir MacBook alarak iOS developer olma yolunda bir karar aldım. Eskiden Flutter Developer olarak çalıştığım için bana yakın olan kısım SwiftUI’dı ve hızlıca bir kaç eğitimle SwiftUI yazmaya başladım. Bu süreçte bir çok küçük proje ve göz bebeğim olan Health Care’i hem bitirme tezi hemde SwiftUI projesi olarak yazdım.</p><p><a href="https://github.com/devmehmetates/Health-Care-Public">GitHub - devmehmetates/Health-Care-Public: Health Care gives tips to people about his/her life to be better.</a></p><p>Sürecim iyiydi fakat <strong>plansızdım</strong>. Bu nedenle ne kadar öğrensem de düzensizlik sebebiyle ne kadar ilerlediğimi bilmiyordum. Daha sonrasında <a href="https://medium.com/u/b963dda1d29d">Yusuf Demirci</a> ile yaptığım bir görüşme hayatımın rotasını çok büyük ölçüde değiştirdi. Bana hatalarımı gösterip nerelerde ilerlemem gerektiğini gösterdi, yani ilk mentorüm oldu. Yaptığımız bir başka görüşmenin sonucunda(Bu görüşme tam olarak 30 aralıkta yapıldı 👀) yusuf abininde önerileri üzerine 1 yıl boyunca kod yazmaya ve her gün bunu paylaşmaya karar verdim. Yukarı da bahsettiğim tweet’i attım ve işe koyuldum.</p><p>Roadmap’im şu şekildeydi;</p><ul><li>100 gün boyunca HackingWithSwift’in UIKit kursunu bitir ve hem Swift hem de UIKit için taze bir başlangıç yap. Kendini 0 gibi düşün. Detayları atlama.</li><li>Sonraki 100 gün boyunca yine HackingWithSwift’in SwiftUI kursunu bitir. Bununla birlikte hem arada geçen süre zarfında Swift’ini geliştir ve tekrar et, hemde iş olanaklarını tamamen değerlendirmek için daha fazla deneyim kazan.</li><li>Geriye kalan 165 gün kendini projelerine ada ve iş başvurularına başla. Böylece mülakat tecrübesi kazan ve bu deneyimlerinle kendini geliştir.</li></ul><p>Ve bunların hepsini gerçekleştirmeyi başardım ❤️‍🔥 Gelelim bu süreç boyunca neler yaptığıma.</p><p><a href="https://github.com/devmehmetates/365-day-of-code">GitHub - devmehmetates/365-day-of-code: A 200-day repository of Swift - UIKit - SwiftUI hosting around 100 projects.</a></p><p>adında bir repo açıp 200 gün boyunca yaptığım tüm projeleri ve yazdığım tüm markdown dosyalarını bu projede topladım. Toplamda 50&#39;ye yakın UIKit, 30&#39;dan fazla da SwiftUI projesi içeriyor.</p><p>Ve sadece bununla kalmadım. Elimde tam <strong>165</strong> gün daha vardı. Bunu da değerlendirmem gerekiyordu.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*FQOD-mXjeOcvo4PR-NiqNQ.png" /><figcaption>Öne Çıkan Uygulamalarım</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*9DUS8htAeoUL4tj_AOMmvQ.png" /><figcaption>iTunes Api ile yaptığım iMusic</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*UIdZ21KxZtU4M4hr4nJuyw.png" /><figcaption>Bir makale ile birlikte MVVM yapısını anlattığım MedExp</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*w5P8k09BEsV01TzvOISvlg.png" /><figcaption>Hobi olarak başlayıp production olacakmış gibi yaptığım Tips For Riot</figcaption></figure><p>Ve bana harika deneyimler kazandıran bu uygulamarı, hatta çok daha fazlasını yaptım. Her uygulamanın bana <strong>farklı</strong> bir şey öğretmesini ve çeşitlilik açısından farklı konulardan olduğunu repoları incelerseniz çok rahat fark edeceksiniz.</p><p>Bu uygulamaların tamamı SwiftUI ve bu benim iş dünyasına girişimi oldukça geciktiren bir durum oldu. Çünkü yatırımımı UIKit’e yapmamıştım. Ve tam bunu nasıl çözeceğimi düşünürken <a href="https://medium.com/u/2c53aca6142e">kodluyoruz</a> ekibinin yapmış olduğu bir Twitter space’ine katıldım. Bir mentorlük başvurusu yaptım ya <a href="https://medium.com/u/a7d98cba1e38">Beyza Ince</a> ile mentorlük programına başladım.</p><p>Bu benim için hayatımın 2. kırılma noktası oldu diyebilirim. Çünkü gerçekten düzenli bir programlamla UIKit tecrübesi ediniyorken, bunu sektörün içinden gerçekten bilgili birinin desteği ile yapıyor olabilmek gerçekten benim için çok büyük bir şanstı. Mentorlük programı boyunca</p><p><a href="https://github.com/devmehmetates/Dude-Money">GitHub - devmehmetates/Dude-Money: An application that allows sharing accounts between friends.</a></p><p>projesini geliştirdim ve harika reviewlar aldım. Bununla yetinmeyip mentorümün desteği ile</p><ul><li><a href="https://betterprogramming.pub/viper-design-pattern-step-by-step-with-example-project-247b3d101a9e">Implementing the Viper Design Pattern in iOS</a></li><li><a href="https://medium.com/ibtech/retain-cycle-in-swift-7f38f05f9dd0">Retain Cycle in Swift</a></li></ul><p>bu harika iki makaleyi de yazarak kendimi geliştirmeye devam ettim. Bu makaleler bana teknik becerilerin yanında kendimi daha iyi nasıl ifade ederim, kendimi nasıl en basit şekilde açıklarım sorularının cevabı oldu.</p><p>Tüm bu süreçlerin asıl amacı “daha iyi bir kariyer sahibi olabilmek” olduğu için planladığım gibi başvurularımı yapmaya başladım ve bir çok kez reddedildim. Bu benim bazen moralimi inanılmaz bozsa da, beni pes ettirmeye yetmedi. Bu konuma geldiğim an kendi kendime “Bu benim işim değil bir hobim, bunun üzerinden para kazabilmem bunu iş yapıyor olsa da sevdiğim için bunu yapıyorum.” diyerek bu olumsuz düşüncelerden sıyrılmaya çalıştım.</p><p>Ve ilk olarak Mobillium’da öğretici bir staj deneyimi yakaladım. Ve bunun hemen ardından QNB Finansbank’da iOS developer olarak işe başladım.</p><p>Özetleyecek olursam eğer iOS developer olmak istiyorsanız, ihtiyacınız olan 2 şey var;</p><ul><li>Kod yazmaya yetebilecek bir MacBook</li><li>Ve hiç bir zaman kaybetmeyeceğiniz bir inanç.</li></ul><p>Bunlara sahip olursanız ve azimli şekilde çalışırsanız kesinlikle başaracaksanız. Geç olsun ve ya erken, elbet başaracaksınız.</p><p>Eğer iOS developer olmak gibi bir planınız varsa benim tavsiyem;</p><ul><li>En başından sonuna kadar kendinize sağlam bi plan yapın ve buna uyun. (Benim planımı da kullanabilirsiniz)</li><li>Belirli aralıklarla birilerinden destek alın. (Bu her şey yolunda gitse bile yapmanız gereken, sizi onaylayacak ya da uyaracak deneyimli birinden istediğiniz ufak bir review olabilir.)</li><li>Çok değil öz çalışın. (Size zaman kazandıracak konu kesinlikle planlamanız. Planlamanız ne kadar iyiyse hedefleriniz o kadar kısa sürede size ulaşır.) (Not: Bu benim tam olarak doğru yapamadığım bir şey. Bu yüzden kaybettiğim neredeyse 2 aylık bir süre!)</li></ul><p>Benim yaptıklarım ama yapmanızı önermediğim şeyler;</p><ul><li>Bazı eğitimler benim hiç işime yaramıyor fakat ben yine de planımda olduğu için yaptım. Bunları yapmamak size zaman kazandıracaktır.</li><li>Çok çalıştım. Bu beni gerçekten yıpratan bir durumdu. Verimli olmasına rağmen gerçekten bazen çok bunaldığım anlar oldu. Bu da pes etmenize sebep olabilir. (Burada bahsettiğim gün içinde 12–13 saat aktif kod yazmanın yıpratıcılığı. 365 gün düzenli kod yazmak oldukça keyifliydi.)</li><li>Mükemmeliyetçi olmayın. Öğrenme döneminde olduğumuz için yeni ve güzel şeyler keşfediyoruz ve bunu uyguluyoruz. Bunu çok sık yapmak projenin ilerleyiş hızını çok fazla yavaşlatıyor. Projeye başlayın ve bitirin. Yeni bir projede yeni öğrendiklerinizi kullanın. Böylece hem daha fazla proje sahibi olursunuz hem de elinizde ilerleyişinizin somut bir kanıtı olur.</li></ul><p>Kapanışa gelelim. Asla pes etmeyin. Bu medium yazısını genel bir motivasyon ve moral kaynağı olarak kullanabilmeniz için hazırladım. Amacım deneyimlerimi aktarıp yaptıklarım ve sonuçlarını göstermekti. Bir kaç kişiye bile bir faydası olursa çok mutlu olurum.</p><p>Herkese Bol Kodlu Mutlu Seneler 🎄</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=75b79ccc94fb" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[MVVM Design Pattern For SwiftUI]]></title>
            <link>https://medium.com/ibtech/mvvm-design-pattern-for-swiftui-ed204f327c9b?source=rss-393f090c04a------2</link>
            <guid isPermaLink="false">https://medium.com/p/ed204f327c9b</guid>
            <category><![CDATA[swiftui]]></category>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[unittest]]></category>
            <category><![CDATA[mvvm]]></category>
            <category><![CDATA[api]]></category>
            <dc:creator><![CDATA[Mehmet Ateş]]></dc:creator>
            <pubDate>Sun, 20 Nov 2022 11:27:35 GMT</pubDate>
            <atom:updated>2022-11-21T06:22:53.768Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/700/1*jDfn5NANYS7CHL2z_7cqyQ.png" /></figure><p>SwiftUI is a great framework that has made things a lot easier since it came into our lives. To use it in the most effective and sustainable way, we must follow a certain pattern. Our topic is design patterns for SwiftUI 💙</p><p>It will be a good article series that we will examine 3 design patterns together. Our first stop is MVVM. Let’s get to know MVVM first.</p><p>A design pattern recommended by Apple for SwiftUI that works really well with Combine. Consisting of 3 layers, this design pattern consists of:</p><ul><li><strong>M</strong>odel: Entities we know very well.</li><li><strong>V</strong>iew: Again, the UI we’re very, very familiar with.</li><li><strong>V</strong>iew<strong>M</strong>odel: It’s the layer that matters to us that’s available to us with MVVM. The part where both business and logic operations are done.</li></ul><p>Now that we have the summary information, let’s look at the relationship between these 3 layers.</p><figure><img alt="MVVM" src="https://cdn-images-1.medium.com/max/700/1*LrySIEguRg79iXfL9RzjCg.png" /><figcaption>MVVM Feed</figcaption></figure><p>Let’s focus on the view model, which is important to MVVM. <strong>For a simple request</strong>, it does the following in order:</p><ul><li>It is triggered by the View.</li><li>Triggers the service for the request.</li><li>The service sends a request to the API and receives an error or response.</li><li>It transmits the response or result it receives to the view model.</li><li>If the received response is an error, the view model returns an error response to the screen and completes the request.</li><li>If a successful response is received, it parses the model and processes the response.</li><li>Passes the rendered model back to the view as requested by the view.</li></ul><p>So <strong>how does it work a logic</strong>?</p><ul><li>It is triggered by the View.</li><li>It does what it wants in itself.</li><li>Reports the result of the operation to the view.</li></ul><p>This is MVVM in its simplest form. Let’s see this in a real project, with real requests, real logic. I wrote an application for this.</p><blockquote><strong>Important Note</strong></blockquote><blockquote>In order to access the contents in the project, you need to define an api key anywhere in the project as follows. You can get the key <a href="https://www.themoviedb.org/settings/api">here</a>.</blockquote><pre>struct AppEnvironments {<br>    static let apiKey: String = &quot;Your Key&quot;<br>}</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*UIdZ21KxZtU4M4hr4nJuyw.png" /></figure><p><a href="https://github.com/devmehmetates/MedExp-MVVM">GitHub - devmehmetates/MedExp-MVVM: This application was created to answer the question of how we can implement the MVVM design pattern in a testable way with SwiftUI.</a></p><p>Let’s take a closer look and explore the beauties of both MVVM and SwiftUI together. Unit Tests included :)</p><p>We have 3 schemes in the application. These;</p><ul><li><strong>Home Screen: </strong>Our discovery screen, filling up with multiple requests. The first screen of the application.</li><li><strong>Search Screen: </strong>A search screen where you can search for movies and TV shows any way you want.</li><li><strong>Detail Screen: </strong>A screen where you can review the contents of movies or series.</li></ul><p>We can start with the Home Screen feed.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/1*XxBj6x85OpOYMARBMDD7_w.png" /></figure><p>As you can see, a view consisting of 1 header tabbar and 6 horizontal scrolls. Header tabbar is filled with top 10 items of popular tv content. So it contains 6 requests in total. Network manager throws the requests for us and sends the response or error to the view model.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ix9AAPRT7qJjZB2FQSLAfA.png" /><figcaption>Network Manager</figcaption></figure><p>This network manager I wrote only allows me to send requests and receive responses in accordance with the API I use. Now let’s come to the view model where we use the request function.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*p2tjOG86zcHzORuomvZ6_g.png" /><figcaption>HomeViewModel</figcaption></figure><ul><li>The first place we will concentrate is protocol. It has a dictionary containing our Media Sections, a boolean indicating the page state, and a function to update the page for the sections. It simply means that we will use them in the view and test them. Also, another thing we need to pay attention to is another protocol that our protocol is connected to.</li><li>Since the successful response results of the requests are the same, I wrote a protocol to avoid code duplication.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*S_m-9hcN2JeZqkdsAYfRjw.png" /><figcaption>Requestable Media List Protocol</figcaption></figure><ul><li>We saw that this hooks into our view model. So our ViewModel is actually an observable object. And it publishes the 2 objects it contains in the protocol.</li><li>The second point we need to focus on is exactly here. Because here, when one of the two objects changes, the view is informed about it. It does this by observing the view model.</li><li>In order to do this, it needs to define it as observed in the view. Otherwise it doesn’t make any sense.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*sbemMK6iOWMzHv9w2oh0nQ.png" /></figure><ul><li>For example, we can see that the loading state directly affects the content of the page. Just look at lines 16 to 20.</li></ul><p>Well, we understand the requests. We already have a few more examples to reinforce. Does ViewModel have another task here? <strong>YES! </strong>All of the above actions happened automatically when the viewmodel was init. Did we mention triggering?</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*WJ1qotJzniifCYM0Sx5b1Q.png" /></figure><p>You will see that there is a method defined as Interface properties above. This method will increase the number of pages to load new movies as our horizontal media scrolls scroll sideways and call the function that will make a new request and do this. It’s too long a sentence 😅.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/296/1*Q_0JVCn9eaMzr7zyk09ojA.gif" /><figcaption>But that’s what it does :)</figcaption></figure><p>If we think a little bit, we can easily understand that it is an operation that is triggered by the view and takes place in the view model, as it is a situation that needs to be done as you scroll.</p><p>There is a nicer place where we can understand this. It’s also Search View. Let’s take a look at it.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/296/1*dJsFRp1VVCtSzdKi4TFAaQ.gif" /><figcaption>Search View</figcaption></figure><p>Here we see the view trigger much more clearly. Every time our search key changes, the request is made again and the page is updated. And the only good thing that provides this is Observable annotation. Its structure is as follows;</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*cl2dBVD07QsVLX2Ydl-NQg.png" /></figure><p>The search key is constantly monitored by the view, and in fact, every hit we make on the keyboard changes that search key. In other words, the search key always changes in the view model and is pressed on the screen again because it is being watched.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*3XS2fjKm_8I1ZV6u2nzRJg.png" /></figure><p>Of course, one of SwiftUI’s magic modifiers, the searchable, should also be thanked for doing so :) They may sound complex or very simple. The only truth will be to experience. So let’s do a challenge with you.</p><p>The view model of the detail view, which is a view with a very complex structure, is not that clean. <strong>Can you refactor this?</strong> I did all the things I wanted you to experience in another branch. Let me tell you what you need to do.</p><p><a href="https://github.com/devmehmetates/MedExp-MVVM/commit/7b702e9cd85e0c596d52b0b250df266b4d1b9314#diff-b71f472f46b7486ba78071d827980f0e46c3c93aea5baf9e3873124dc3d73fda">refactoring on home view model, update home view and network manager ... · devmehmetates/MedExp-MVVM@7b702e9</a></p><p>First review this commit. You will see that the Homeview model is similar to the DetailViewModel and how I made it clean. Implement this in detail view.</p><p>Now fork the project and try doing this challenge. You must create and publish new objects. Maybe you don’t publish and see what happens. Share your refactor on twitter by tagging me 💙. So we can see lots of different codes.</p><p>Everything went well, let’s get to the test. You’ll see that we’re going to need some change here. Because Unit tests “are functions triggered?” It clarifies the question in our minds. Results are the task of integration tests. So where do we make changes?</p><p>Unfortunately, our project is not very testable in its current state. But we can make it testable. (This required a lot of changes. Please review the differences by switching between branches.)</p><p>I’ll just talk about the changes and tests we made for the HomeViewModel. Let’s start.</p><p>In HomeViewmodel, we could do our operations directly without defining an object with the singleton property of NetworkManager before. But when it came to mocking, this put us in a snag and made our code untestable. Therefore, I connected the network manager to the homeviewmodel with a protocol and mocked the network manager using the protocol.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*0EJ-oZ6PQpadhq8vnLEzaA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*svvfPK9XJquuqZOt3XeEdw.png" /></figure><p>Let me explain to you why I did this. We already know that when the HomeViewModel functions run, it throws a request. While doing this, it used to create a Network manager instantly, access its function and then destroy it. That is, the part I had to test was a momentary existence and disappearing with extinction.</p><p>With this change, HomeViewModel now has a network manager object and performs all operations on it. In this way, I can create a mock in my tests and perform operations on it. If you look carefully at the tests, it was enough for me to check that the network manager was triggered in all of them. Because the HomeViewModel’s job is to bring us the data.</p><p>All this time we talked about MVVM and tests. Want to learn a little about SwiftUI? Let’s look at performance improvements with SwiftUI</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/296/1*MDlknPBInU19SE8pfj446g.gif" /></figure><p>I move the cards back and forth. And you notice that some of the images are constantly being reloaded. This is a feature that reduces instant memory usage. And we use it in LazyVStack, LazyHStack, List etc components. On this page, you can experience that the same feature is used in sections by scrolling up and down.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/296/1*0d_n-HdXm2y8mU4LcsMf6w.gif" /></figure><p>The best optimization I did unconditionally was to install a lazy push system in nagivation. Instantly init the given page destination with SwiftUI NavigationLink. Even if the entire page is lazy, there are 32 instantly init DetailViewModels on this page. We prevented all view models from being created by wrapping this with lazynavigate and creating the view as soon as it is opened. You can access it at the link below.</p><p><a href="https://github.com/devmehmetates/MedExp-MVVM/commit/094d58a65d056620f37c6c4ee4758701b79bc4ac">performance optimization · devmehmetates/MedExp-MVVM@094d58a</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/1*oRJE27kk5g-L3wvhuPxsmg.png" /></figure><p>Another great feature that SwiftUI provides is redacted. It will automatically make the page look like a placeholder and make it different until your data is loaded.</p><p>Everything looks perfect. So could it be better? Let’s decide this together. With Part 2, let’s write a new application with viper design pattern and see what has changed. I will update here when I add the article.</p><p>Also my SPM Packages I use in this project :)</p><ul><li><a href="https://github.com/devmehmetates/StickyAsyncImageSwiftUI">StickyAsyncImageSwiftUI</a></li><li><a href="https://github.com/devmehmetates/SwiftUIAnimatedRingCharts">SwiftUIAnimatedRingCharts</a></li></ul><p>Don’t forget to follow me to be informed about all my developments and new articles. Happy coding 💙🧡</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ed204f327c9b" width="1" height="1" alt=""><hr><p><a href="https://medium.com/ibtech/mvvm-design-pattern-for-swiftui-ed204f327c9b">MVVM Design Pattern For SwiftUI</a> was originally published in <a href="https://medium.com/ibtech">IBTech</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Retain Cycle in Swift]]></title>
            <link>https://medium.com/ibtech/retain-cycle-in-swift-7f38f05f9dd0?source=rss-393f090c04a------2</link>
            <guid isPermaLink="false">https://medium.com/p/7f38f05f9dd0</guid>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[retain-cycle]]></category>
            <category><![CDATA[ios]]></category>
            <dc:creator><![CDATA[Mehmet Ateş]]></dc:creator>
            <pubDate>Mon, 31 Oct 2022 09:43:14 GMT</pubDate>
            <atom:updated>2022-11-01T12:01:01.519Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/700/1*iSIxnbX-bhlIU7BC3fWKqw.png" /></figure><p>Memories. Indispensable parts of our technological devices. How well do we manage them as developers? Let’s learn what Retain Cycle is, which is a part of this topic today, and how we can manage it.</p><p>Our first topic is <a href="https://docs.swift.org/swift-book/LanguageGuide/AutomaticReferenceCounting.html"><strong>ARC</strong></a></p><p>We just said retain cycle, what’s the point of ARC? A.R.C, namely <strong>A</strong>utomatic <strong>R</strong>eference <strong>C</strong>ounting, is a kind of memory cleaning tool that Apple has presented to us. It <strong>cleans up our redundant references </strong>and frees us up a good memory. If we write the kind of code that can use it, of course.</p><p>If we write the appropriate code, there is no problem anyway. We couldn’t write, or we didn’t know. So what will we do 😱? Let’s see.</p><p>I have written a small project for you so that you can experience this beautifully. Please feel free to fork the project and experience it with me.</p><p><a href="https://github.com/devmehmetates/RetainCycleUIKit">GitHub - devmehmetates/RetainCycleUIKit</a></p><p>All we have to do is run the project first and go through the pages a few times. You won’t be able to do anything else anyway ☺️.</p><ul><li>For example, go to the last page and then back to the first page. Then click on the button(Debug Memory Graph) shown below.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*31OKdsqSNCsqRq1RoLhX0g.png" /></figure><ul><li>Your application will stop. And your Xcode will look like this. See where I’ve yellow-marked below. We are now on the first page, but there are precisely 4 view models in memory.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*RTHqO0F1k6fUo6QpeFuqsQ.png" /></figure><ul><li>For a better understanding, press the button(Continue) I marked in red and let the application continue. Then repeat the first navigate operation 2 more times. And click the <strong>Debug Memory Graph<em> </em></strong>button again.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*LSsRQkoGAOdTlipGiHmp9Q.png" /></figure><ul><li>Our number has reached 10! So why 10 do you think? Our first page in existence has never died. But the 3 pages we created by going forward died every time we came back. We repeated the process 3 times in total and since we have 3 pages, we have created 9 view models. Of course, the view model of our first page that never died. Thus, a total of 10 view models are currently kept in memory. <strong>Nightmare.</strong></li></ul><p>So far, I hope you understand everything. If you don’t understand, repeat the steps and continue until you do. So let’s continue. What caused this?</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*3ZrNLQ5koczoryVD4fL9rA.png" /></figure><p>The above code is common to all view controllers. They all init a view model.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*eI_8hX1nhsdSVHMGfDgOdg.png" /></figure><p>All view models derive from a single class and require a view reference to itself in the common view model. This means that for us.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*p5_5Jc--YdsJiNXHyPcWJw.png" /></figure><p>View controller has view model and view model has view Controller 🤯. And yes! Now you know what retain cycle.</p><p>Okay, but there is a way out of this, right? Because this is really scary. Of course there is. With only a one-word type designation. Let’s learn the bride types first and then get rid of this scourge.</p><p>Reference types are divided into 3. Shall we meet them?</p><ul><li><strong>Strong: </strong>I am a strong reference 💪🏼. Whether a class holds me or not, I keep that class. And I won’t be lost until you destroy me. (Currently, we have two classes of this type.)</li><li><strong>Weak: </strong>Hi I’m weak reference 🥲. If a class doesn’t hold me, I don’t exist. I live with it, I die with it.</li><li><strong>Unowned: </strong>Hi, I’m unowned 🤐. I expect a class to hold me. But if you want to use me, make sure I go before the class holding me. If you don’t I will crash your app 😵.</li></ul><p>Which one do you think we should use? Our type is strong anyway so we need to use it. Weak or Unowned? Let’s try both in our case.</p><p>Let’s start with the Weak. Open the CommonViewModel as below and set the view to weak.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*YW5G4zr7ebAv_vee_OmWQw.png" /></figure><p>Run the application again and go to the last page 3 times in the same way and come back. Then open the Debug Memory Graph.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_1ReKzOn5kax0VBZHkq6Vw.png" /></figure><p>Fantastic. We are currently on the first page and only one view model is in memory, just as we wanted. Also there are 9 outputs in the debug logs.</p><pre><strong>Hi, Am i dead? Yes :( //Page 3<br>Hi, Am i dead? Yes :( //Page 2<br>Hi, Am i dead? Yes :( //Page 1<br>Hi, Am i dead? Yes :( //Page 3<br>Hi, Am i dead? Yes :( //Page 2<br>Hi, Am i dead? Yes :( //Page 1<br>Hi, Am i dead? Yes :( //Page 3<br>Hi, Am i dead? Yes :( //Page 2<br>Hi, Am i dead? Yes :( //Page 1</strong></pre><p>So how did this happen? Our View models have a deinit function that will do this print every time it disappears. So it only works when they die. Since we defined it as weak, view now holds the view model. And so when the view dies, the view model also dies. Well, it’s great.</p><p>Now let’s try the same for unowned. The result will be the same. But let’s change one more thing and understand the situation better. Let’s write a deinit function inside the whole view controller.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Ki3Qjpn-qqNs7b0ZwbLAXA.png" /></figure><p>Like this. And then let’s go to the last page and back to the first page. Repeat this time only once.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*gVpkSwS_f5sSdxBrsN8atA.png" /></figure><p>This is how we will see the Debug console. As you can see, the view I gave as unowned dies before the viewmodel, so the application runs smoothly without any problems.</p><p>How about a little reinforcement? 🧐</p><p>We have 2 more branches to understand the subject better. You can switch to them as follows. (Or you can make changes from a git-client of your choice and examine the code.)</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*CxPZLXjDx0isS8ne6oh9LA.png" /></figure><p>First, let’s move on to our bonus branch. What did we change? You can view them all here, but I’ll summarize.</p><p><a href="https://github.com/devmehmetates/RetainCycleUIKit/commit/db3f5855bbadd0a3bdd68414626ba4bf3b868f05">common viewModel now really common · devmehmetates/RetainCycleUIKit@db3f585</a></p><p>What I did was create a view model on root and distribute it to other views. And the view model could never be created again because the root page never died. In this way, even though I did not specify weak or unowned on the view model, the retain cycle did not occur.</p><p>Let’s take a look at bonus2, too. The only thing I did here was to create the view model I shared in page1, not root. Again all the changes are here.</p><p><a href="https://github.com/devmehmetates/RetainCycleUIKit/commit/718f022a00336e9fbd0b6343944bf78d6860cab8">common view model init place changed · devmehmetates/RetainCycleUIKit@718f022</a></p><p>So what did that change? Creating and sharing a view model in Page1 has reduced the number of retain cycles that occur, but it will continue to occur as long as I don’t use weak. Because page1 can die and therefore the view model is unfortunately freed in memory.</p><p>In summary, weak or unowned are very important types that we should use in such cases. But it is also very important that we use it in the right place and in the right way. This is something we can get by experiencing a lot of things 🦸🏼.</p><h4>Closing</h4><p>We discussed the subject of retain cycle, which is a very complex subject to explain as well as to understand. I hope everything is clear in your mind. See you on future issues. Happy coding, with Swift 🧡.</p><h4>Resource(s)</h4><ul><li><a href="https://docs.swift.org/swift-book/LanguageGuide/AutomaticReferenceCounting.html">Apple ARC Document</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=7f38f05f9dd0" width="1" height="1" alt=""><hr><p><a href="https://medium.com/ibtech/retain-cycle-in-swift-7f38f05f9dd0">Retain Cycle in Swift</a> was originally published in <a href="https://medium.com/ibtech">IBTech</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Implementing the Viper Design Pattern in iOS]]></title>
            <link>https://medium.com/better-programming/viper-design-pattern-step-by-step-with-example-project-247b3d101a9e?source=rss-393f090c04a------2</link>
            <guid isPermaLink="false">https://medium.com/p/247b3d101a9e</guid>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[design-patterns]]></category>
            <category><![CDATA[ios]]></category>
            <dc:creator><![CDATA[Mehmet Ateş]]></dc:creator>
            <pubDate>Sat, 10 Sep 2022 10:42:17 GMT</pubDate>
            <atom:updated>2022-09-15T09:40:36.482Z</atom:updated>
            <content:encoded><![CDATA[<h4>A step-by-step guide with an example project</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*-d2wt7RvAdtIAFMt" /><figcaption>Photo by <a href="https://unsplash.com/@lazizli?utm_source=medium&amp;utm_medium=referral">Lala Azizli</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>Design patterns! In the software world, they are indispensable for us to be able to work on sustainable code bases that prevent us from writing code on our own. What about Viper? It’s a popular design pattern we use to develop iOS apps. So, let’s get to know it better and embark on a long-term adventure.</p><p>View, What else could it be? The layer that contains the User Interface elements and can only communicate with the Presenter.</p><p>Interactor, This layer connects us to real life and again only communicates with the presenter.</p><p>Presenter, Viper’s apple of the eye. The layer where everything happens. In short, our bridge connecting all layers.</p><p>Entity (Optional), Our models. Seriously only models. Our structs or classes.</p><p>Router, Viper’s bigbang. Our brave layer is in charge of the creation of the module and all layers (including itself).</p><p>We met our layers. Yes, yes they are also very pleased to meet you. So we are ready to answer this.</p><h3><strong>Why should I or should I not use Viper?</strong></h3><p>No slander or praise here. There are only facts.</p><p><strong>Let’s start with the positives.</strong></p><ul><li>Viper is incredibly testable.</li><li>Viper provides the code layout very well.</li><li>Readability is very high.</li></ul><p><strong>Let’s look at the downsides.</strong></p><ul><li>Viper is very bulky. Too many layers too much time!</li><li>It is complex. You can get lost in folders. Or you find the exact path.</li></ul><p>Check out these items now.</p><ul><li>You want to release an app quickly. Really fast. For example with SwiftUI. It would be better not to use it.</li><li>You have embarked on a huge project with UIKit. It needs to be tested. Definitely use it.</li></ul><h3>Understanding the VIPER</h3><p>Viper is a headache if you’ve never done protocol-oriented programming. But once you get used to it, it goes away. This article is for exactly that. Let’s roll up our sleeves and get started.</p><p>I wrote an application for this, while you are reading the article, you can examine it and follow how the code works.</p><p><a href="https://github.com/devmehmetates/Viper-Example">GitHub - devmehmetates/Viper-Example</a></p><p>I think our first job is to complete the view layer that we always do. Here I created a simple list view using the compositional layout of the UICollectionView. Even doing this I will need the <strong>Presenter</strong> but for now let’s do it in the view controller.</p><h3><strong>View</strong></h3><p>The code you see below is definitely not suitable for <strong>Viper ❌</strong></p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/f591be147608245dea784d88e2e12731/href">https://medium.com/media/f591be147608245dea784d88e2e12731/href</a></iframe><figure><img alt="Collection View Base" src="https://cdn-images-1.medium.com/max/438/1*YSvfMvbOSs83iaFol5XDgQ.png" /></figure><p>The above code gives the same output. Cells have been successfully created and a base has been prepared. Now let’s pass this code to Viper by keeping the view fixed. As I mentioned earlier, Viper uses P.O.P quite actively. Therefore, we define all view operations in the presenter in the interface of the view. The purpose of this is to be able to access from the presenter. Let’s take a look at the edited version.</p><h3><strong>Viper solution ✅</strong></h3><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/5c57a56917e3ef73d23f1145f1f36f11/href">https://medium.com/media/5c57a56917e3ef73d23f1145f1f36f11/href</a></iframe><p>You are looking at a huge piece of code and you may not understand what would have changed. First of all, make sure that this code gives the same output. We currently have a presenter that does not appear in the background, and this can be confusing. But worry not! Everything will be clear soon.</p><ul><li>The first change, of course, protocol. We added 2 functions and defined in ViewController. What we need to do now is to call it in the presenter wherever we need it. This is currently<strong> </strong>presenter.notifyViewDidLoad()</li><li>The second change is the numberOf functions. These functions may vary by server or local services. So this number should be passed to the view by the server. This way, if there is a change, the view can be aware of it.</li><li>The last change is the setTitle function. The reason for transferring this to the presenter is actually the same. Because we can set this by the services.</li></ul><p>As you can see, what we’re actually doing is separating all logical operations. And at the same time, we have written code for the future. Although this slows it down at first, it will speed up a lot in the future. And remember. <strong>The view is not finished yet. </strong>Now let’s write a service and create our Interactor layer.</p><h3>Interactor, Service, and Entity</h3><p>Since these are related to each other, it would be best to process them together. Interactor connects with the service and processes the model for us. We will have a very simple model and a service tasked with reading it.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/b9a00b65805e9e97bf12cd4d5a235474/href">https://medium.com/media/b9a00b65805e9e97bf12cd4d5a235474/href</a></iframe><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/46ddc2bd1fcdabd925a5e79ec97924f2/href">https://medium.com/media/46ddc2bd1fcdabd925a5e79ec97924f2/href</a></iframe><p>As you can see, we have a fairly simple model and registration system. It has functions for both reading and writing. To get the point across, think of it this way, this is the layer where we communicate for backend operations. We fired exactly one request and we’re getting an array back.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/33d2ef2dcd5c0ce108304ded97546951/href">https://medium.com/media/33d2ef2dcd5c0ce108304ded97546951/href</a></iframe><p>As you can see, nothing complicated. We first recorded our data and then read it. Thus, Interactor fulfilled its own responsibility. Now let’s come to where everything connects, namely the Presenter.</p><blockquote>Important note: You can ignore line 16 here. Its only purpose is to create a data for you on the first run of your application. If you want, fork the application, run it once and delete this line.<strong> The result will be the same.</strong></blockquote><h3>Presenter</h3><p>We’ve really come to the layer where almost everything happens. This layer should now look like this.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/9d594bad4358587c14adb027beedef66/href">https://medium.com/media/9d594bad4358587c14adb027beedef66/href</a></iframe><p>Slow down here!! This layer is the most important layer for the viper, and we have questions to ask. These are the questions we will ask why. Let’s explain our layer slowly.</p><p>See the protocol. It has all the functions we use on the view controller. It is defined in the interface setup and it is clear what they do. Perfect!</p><p>Take a look at the NotifyViewDidLoad function. “view?” We see the expressions. These are actually the functions in the interface of the viewController that we made at the beginning. And they are triggered in the presenter and work great. Everything seems to be explained. Now let’s move on to our questions :)</p><ul><li><strong>Why are variables private?</strong> The reason is that the variables represent our classes. And it wants us to perform viper logic operations on the presenter. If we leave it to public access, we can directly access the router or interactor through the ViewControler. We shouldn’t be able to do this.</li><li><strong>Why is the view weak while the others are strong? </strong>The reason is the <strong>retain cycle. </strong>The presenter is defined strongly on the view controller. If we also define view as strong on the presenter, these two classes will never leave each other. And that’s a lousy experience for our memory management. <strong>What about the others? </strong>Do you think this applies to the interactor? Presenter is not even defined. If we keep it weak, the interactor will not be able to find a branch to hold on to and will disappear :(</li><li><strong>Well, I understand the classes, but why is </strong><strong>datas private? </strong>Remember it’s there for presenter logic. This is related to our first question but not exactly the same. If we open this data as public, we are more likely to “inadvertently” perform logic operations on the View Controller. Like getting the first data :)</li></ul><p>I think we got through the hardest part of the job.<strong> If you are confused about the retain cycle, I suggest you look into it.</strong> Now then, we can create our final layer and make our final edits.</p><h3>Router</h3><p>This is where the whole page starts. It will create all the layers and give a view for us. It should look like this for now.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/2e8d7f2ed6da64604d5ac076631cdd70/href">https://medium.com/media/2e8d7f2ed6da64604d5ac076631cdd70/href</a></iframe><p><strong>Come on, what is this? Why is the protocol empty? Why do we keep it empty? </strong>In fact, it’s completely ready for use when we need it, for the reason. And remember, the presenter is created through interfaces. Classic init operations and a fallback viewController.</p><p><strong>But, then the router is ok too. Where and how will I use it? </strong>I prepared a tab bar controller for you. Of course, it was created with viper too. We have to do something in the tab bar controller. Like initializing the ViewController?</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/7392a788cefcfafd24ae17639b329417/href">https://medium.com/media/7392a788cefcfafd24ae17639b329417/href</a></iframe><p>Don’t get confused here. <strong>Just focus on line 18.</strong> We saw our router. We have run our function. And we started a <strong>Viper Flow. </strong>Now all the codes we wrote are active.</p><h3>Final Touches</h3><p>We have done a lot of operations, but we still haven’t processed our data into the view. Now it’s time to define our view. There are only 2 steps we need to do for this.</p><ul><li>The first is to get the data by index in the presenter.</li><li>The second is to use this data in the cell configuration.</li></ul><pre><strong>protocol</strong> HomePresenterInterface: AnyObject {<br>...<br>   <strong>func</strong> getDataByIndex(_ index: Int) -&gt; BaseModel?<br>...<br>}</pre><p>Let’s add this function to our protocol. So we can get a base model by index. Xcode should be mad at us the moment we add this.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*D1CrjYm7dw-vYaSXosiGlQ.png" /></figure><p>Let’s complete the function without further angering Xcode.</p><pre><strong>func</strong> getDataByIndex(_ index: Int) -&gt; BaseModel? {<br>   datas?[index]<br>}</pre><p>Good, now let’s come to the view part.</p><pre>cell.configureLabels(with: presenter?.getDataByIndex(indexPath.row))</pre><p>As you can see it is one line and works flawlessly. Now let’s open our application. We should be seeing our data.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/438/1*gmI_YWgFULpDM05l_GxqCg.png" /></figure><p>Fantastic!<strong> </strong>Thus, we have completed our application. Of course, if we wrote Viper, not if we didn’t write tests for our app. Come on, you’re not tired. Let’s also write our unit tests and it’s all over.</p><h3>Unit Tests</h3><p>We’re going to do a few really cool things for this part. I want you to review this <a href="https://github.com/seanhenry/SwiftMockGeneratorForXcode">link</a>. I think you can install it easily. It’s pretty simple. If you have successfully completed the installation, let’s include our project and continue. Before that, let me explain why we do this.</p><p>We copy the classes to be tested with the mock concept, and thanks to the generator we have set up, we can perform the test operations in seconds with the help of protocols. So let’s do it.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/50cf84e33bbecfcfb1b0f31656c025af/href">https://medium.com/media/50cf84e33bbecfcfb1b0f31656c025af/href</a></iframe><p>Are we suddenly stunned? Don’t worry, this is a file that you will create automatically. So it was created by the mock generator linked above.</p><p><strong>If you don’t understand how it’s done this way :)</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*L_Azggtg6wLc_EcjzfiZBA.png" /></figure><p>Now let’s talk about why we create it and how we will use it. Take a look at the interactor file to remember. There is only one variable in the protocol. And in the mock file, the variables required for testing this are kept. It’s normal to be confused here. Now, when I create a unit test and elaborate on it, you will understand it very clearly.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/177788ade08d32942d9d43aa27c25a9c/href">https://medium.com/media/177788ade08d32942d9d43aa27c25a9c/href</a></iframe><p>Here you may notice that other classes have mock classes. Except for presenter only. We named it Viper’s apple because we do everything here. We named it Viper’s apple because we do everything here.</p><p>Now understand this phrase. By giving our mock classes to the router, we enabled the layers defined in the presenter to be mocked. In this way, the view class triggered via the presenter will be Mock and we will be able to test it. Because the purpose of unit tests is to check if a function triggers a class.</p><p>Super, now let’s review our test. First, the presenter function is called and the view mock class is triggered. so the variable in our mock class changes and our test is successful. Let’s take a closer look at this function.</p><pre><strong>func</strong> testNotifyViewDidLoad() {<br>   <strong> homePresenter.notifyViewDidLoad()</strong><br>    XCTAssertTrue(homeView.invokedSetupView)<br>    XCTAssertTrue(homeView.invokedSetTitle)<br>}</pre><p>In our first line, we trigger a function from the presenter. This function is exactly like below:</p><pre><strong>func</strong> notifyViewDidLoad() {<br>    <strong>view?.setupView()<br>    view?.setTitle(with: &quot;Home&quot;)</strong><br>    fetchDatas()<br>}</pre><p>As you can see, our function is triggered by 2 functions defined in view. Here are the functions in our mock class! For this reason, we go and check that the variables in our mock class are true so that we can make sure it is triggered. This is our target. To see it much more clearly and understand the event, you can update the function yourself as follows and renew the test.</p><pre><strong>func</strong> testNotifyViewDidLoad() {<br><strong>    XCTAssertFalse(homeView.invokedSetupView)<br>    XCTAssertFalse(homeView.invokedSetTitle)   </strong><br>    homePresenter.notifyViewDidLoad()<br>    XCTAssertTrue(homeView.invokedSetupView)<br>    XCTAssertTrue(homeView.invokedSetTitle)<br>}</pre><p>The test will still be successful</p><h3>Closing</h3><p>And you entered the world of viper with fast steps. Fork the project so that this entire article comes to mind. Then play around and try to discover the changes.</p><p><strong>There are a few situations I want you to experience.</strong></p><ul><li>To better understand the concept of weak on the presenter, add and delete weak. Keep track of references and objects with Breakpoint.</li><li>Edit the Interactor, Entity, and Service. The stage is yours. Can you print a data from the Internet like this? It would be nice to have things sortable :)</li><li>Create a sorting algorithm. This will make it clear how you use the presenter.</li></ul><p>You did all this. And you want to make sure it’s correct. Don’t worry, of course I’ve thought about this as well. Check out the branches! You will see a branch named advanced. Go checkout and check your solutions.</p><h3>Note</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*aEjHm-dDSBGG7ei-h8Hxmg.png" /></figure><p>In the advanced branch, the application will appear in this state. The data comes and is updated entirely over the internet. There is so much you can improve even more. You can try :)</p><h3>Resources</h3><p>An article that I definitely recommend and take as an <a href="https://medium.com/trendyol-tech/creating-an-ios-viper-module-step-by-step-guide-cd1f414b7dd3">example</a>.</p><p>I would also like to thank my <a href="https://medium.com/@beyza.ince">mentor</a> who supported me while preparing this article 🥹</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=247b3d101a9e" width="1" height="1" alt=""><hr><p><a href="https://medium.com/better-programming/viper-design-pattern-step-by-step-with-example-project-247b3d101a9e">Implementing the Viper Design Pattern in iOS</a> was originally published in <a href="https://betterprogramming.pub">Better Programming</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>