<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های پوریا دلنواز</title>
        <link>https://virgool.io/feed/@porya</link>
        <description>برنامه نویس بک اند. از عشاق دات نت و Angular. برنامه نویس iOS</description>
        <language>fa</language>
        <pubDate>2026-06-16 13:53:39</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/91/avatar/fLNkOo.png?height=120&amp;width=120</url>
            <title>پوریا دلنواز</title>
            <link>https://virgool.io/@porya</link>
        </image>

                    <item>
                <title>ارتباط و سینک اپلیکیشن iOS با Dropbox (قسمت اول)</title>
                <link>https://virgool.io/@porya/sync-user-ios-data-using-dropbox-u08il3iktjpu</link>
                <description>اگر شما هم همیشه به این فکر بودید که اطلاعات لوکال اپلیکیشنتون که روی دیواس iOS کاربر هست رو چجوری می‌شه یه جای امن و قابل دسترس برای کاربر بکاپ گرفت، این نوشته مربوط به شماست.این ایده بر این اساس شکل گرفت که نیاز بود دیتابیس و فایل های لوکال کاربر یه جایی به جز بکند سرور، و جایی که برای کاربر های عادی هم قابل دسترس باشه، بکاپ گرفت تا اگه کاربر دیوایسشو عوض کرد بتونه به راحتی اطلاعات دیوایس قدیمیش رو با دیوایس جدیدش سینک کنه و خب بله، اپلیکیشن ما Cloud-Base نبود و بخاطر بالا بودن حجم فایل های لوکالی کاربر، محدود بودن فضای بکند سرور و تعداد کاربر های زیادی که داشتیم امکان ذخیره فایل ها روی سرور ممکن نبود.این دقیقا کاری هست که WhatsApp با گوگل درایو انجام میده و به دلیل خصومت شخصی بنده با گوگل، تصمیم گرفتم که برای این کار از Dropbox استفاده کنم.مرحله اول: ساخت اپ OAuth2 برای Dropboxاگر که اکانت دراپ باکس ندارید، همین الان می‌تونید از طریق این لینک برای خودتون یه اکانت بسازید. ساخت حساب کاربری رایگان هست و مقدار محدودی هم حجم رایگان در اختیارتون قرار میده که خب اگر قرار هست به صورت جدی برای اپلیکیشنتون ازین سیستم استفاده کنید، احتمالا باید حجم بخرید که خب قیمتش نسبتا ارزون هست. حداقل ارزون تر از افزایش حجم بکند سرور.بعد از ورود به حساب دراپ باکستون برای ساختن یک اپ OAuth2 که در واقع پل ارتباطی هست بین اپلیکیشن iOS و حساب کاربری دراپ باکستون، به این لینک مراجعه کنید.بعد از ورود به صفحه روی دکمه Create App کلیک کنید و فرم رو بر اساس نیاز های خودتون کامل کنیدمن برای این آموزش از Dropbox API استفاده می‌کنم و دسترسی کامل به دراپ باکسم رو درخواست می‌کنم.بعد ازین که اپلیکیشن ساخته شد، شما به صفحه تنضیمات اپ ریدایرکت می‌شید. ما برای این آموزش به ۲ کلید App Key و Access Token نیاز داریم. برای تولید کلید Access Token به روی دکمه Generated access token کلیک کنید.مرحله دوم: نصب فریم‌ورک روی پروژهبرای نصب فریم‌ورک مربوطه دراپ باکس از CocoaPods استفاده می‌کنیم.اگر که نمی‌دونید CocoaPods چی هست و یا تا حالا ازش استفاده نکردید پیشنهاد می‌کنم که قبل از خوندن ادامه این مطلب یه سری به این لینک بزنید.فریمورک رسمی دراپ‌باکس رو با این پاد می‌تونید روی پروژه نصب کنید:pod &#039;ObjectiveDropboxOfficial&#039;من توی این آموزش دارم از ورژن ۹.۰.۱۵ این فریم‌ورک استفاده می‌کنم و ممکنه کدهای به کار رفته توی این آموزش با ورژن های قبلی یا بعدی متفاوت باشه.مرحله سوم: کانفیگ کردن پروژهخب بعد ازین که فریم‌ورک روی پروژه نصب شد، نوبت به کانفیگ کردن پروژه می‌رسه.اول به سراغ فایل info.plist می‌ریم. بر اساس تغییرات امنیتی که اپل توی کنفرانس WWDC 2015 معرفی کرد باید این فایل رو برای برقراری ارتباط با api دراپ باکس تغییر بدیم.فایل info.plist رو به صورت سورس کد باز کنید و این کد رو بهش اضافه کنید:&lt;key&gt;LSApplicationQueriesSchemes&lt;/key&gt;
    &lt;array&gt;
        &lt;string&gt;dbapi-8-emm&lt;/string&gt;
        &lt;string&gt;dbapi-2&lt;/string&gt;
    &lt;/array&gt;این کد به SDK اجازه میده که تعیین کنه که SDK رسمی هست و قرار هست که از OAuth ورژن 2  استفاده کنه.بعد از این نیاز هست این کد رو هم اضافه کنید تا api متوجه شه که SDK قرار هست با کدوم اپ OAuth2 کار کنه:&lt;key&gt;CFBundleURLTypes&lt;/key&gt;
    &lt;array&gt;
        &lt;dict&gt;
            &lt;key&gt;CFBundleURLSchemes&lt;/key&gt;
            &lt;array&gt;
                &lt;string&gt;db-&lt;APP_KEY&gt;&lt;/string&gt;
            &lt;/array&gt;
            &lt;key&gt;CFBundleURLName&lt;/key&gt;
            &lt;string&gt;&lt;/string&gt;
        &lt;/dict&gt;
    &lt;/array&gt;در اینجا &lt;APP_KEY&gt; رو با کدی که در مرحله اول گرفتید عوض کنید.فایل info.plist در آخر باید به شکل زیر در بیاد:احتمالا همینجوری که متوجه شدید این فریم ورک Objective-C هست اما نگران نباشید چون که می‌تونید از همین هم توی پروژه‌ی Swift استفاده کنید. فقط کافیه که YOUR_PROJECT-Bridging-Header.h هدر این فریم ورک رو اضافه کنید و سوئیفت بنویسید.این فایل احتمالا به صورت خودکار به پروژه اضافه میشه اما اگه نشد نگران نباشید، یه فایل هدر خودتون بسازید و آدرس رو در تنظیمات پروژه، در تب Build Setting در Swift Compiler - General و Objective-C Bridging Header اضافه کنید.هدر این فریم‌ورک #import &lt;ObjectiveDropboxOfficial/ObjectiveDropboxOfficial.h&gt;هست. اگر که از پروژه آبجکتیو سی استفاده می‌کنید این رو باید به فایل هدر اون کلاس اضافه کنید.مرحله چهارم: شروع کد نویسیمن توی این مقاله تصمیم دارم که هم کد سوئیفت رو باهاتون به اشتراک بذارم و هم کد آبجکتیو سی رو.خب برای این که اپلیکیشن به اپ OAuth کانکت شه ما نیاز به Access Token داریم که اون رو توی مرحله اول جنریت کردیم و حالا می‌خوایم ازون استفاده کنیم. اما توی این حالت کاربر صرفا می‌تونه فایل هاش رو روی دراپ باکس شما آپلود کنه. اگر که کاربر بخواد فایل هاش رو روی دراپ باکس خودش آپلود کنه نیاز هست که ابتدا به اپ OAuth شما اجازه دسترسی بده و Access Token خودش رو بگیره.در iOS برای اجازه دسترسی گرفتن ۲ راه وجود داره: راه مستقیم که به این صورت عمل می‌کنه که اگر اپلیکیشن دراپ باکس روی دیوایس کاربر نصب باشه وارد اون اپلیکیشن می‌شه، مجوز دسترسی رو صادر می‌کنه و دوباره به اپ شما بر می‌گرده با دست پر! که خب منظورم همون Access Token هست.از طریق سافاری که خب برای وقتی هست که کاربر اپلیکیشن دراپ باکس رو روی دیوایسش نداره. برای این کار از SFSafariViewController استفاده می‌شه. باقی ماجرا روی سافاری اتفاق می‌وفته و باز به اپلیکیشن شما بر می‌گرده.ولی خب من برای شروع کار توی این قسمت و برای این که این داستان خیلی پیچیده نشده، تصمیم دارم که از Access Tokenی که خودمون تولید کردیم استفاده کنم و با دراپ باکس ارتباط برقرار کنم و توی قسمت بعدی وارد مسائل گرفتن مجوز برای هر کاربر می‌شم.در ابتدا ما باید یک کلاینت دراپ باکس بسازیم که قرار هست که به api دستور بده.کد آبجکتیو سی: DBUserClient *client = [[DBUserClient alloc] initWithAccessToken:@&quot;&lt;YOUR_ACCESS_TOKEN&gt;&quot;];کد سوئیفت:var client = DBUserClient(accessToken: &quot;&lt;YOUR_ACCESS_TOKEN&gt;&quot;)خب حالا ما با آبجکت clientی که ساختیم می‌تونیم به api دستور بدیم. برای دست گرمی ابتدا می‌خوایم صرفا یه سری فولدر رو به صورت یک Path توی Root دراپ باکس بسازیمکد آبجکتیو سی:[[client.filesRoutes createFolder:@&quot;/test/path/in/Dropbox/account&quot;]
    setResponseBlock:^(DBFILESFolderMetadata *result, DBFILESCreateFolderError *routeError, DBRequestError *networkError) {
      if (result) {
        NSLog(@&quot;%@\n&quot;, result);
      } else {
        NSLog(@&quot;%@\n%@\n&quot;, routeError, networkError);
      }
    }];
    
کد سوئیفت:client.filesRoutes.createFolder(&quot;/test/path/in/Dropbox/account&quot;).responseBlock = { result, routeError, networkError in    if result != nil {        if let aResult = result {            print(&quot;\(aResult)\n&quot;)        }    } else {        if let anError = routeError, let anError1 = networkError {            print(&quot;\(anError)\n\(anError1)\n&quot;)        }    }}بعد از این که دستور ارسال شد، ریسپانس توی responseBlock میاد که خب اگه کار رو درست انجام داده باشیم Result==True هست و بعد می‌تونیم بریم ببینیم که آیا واقعا فولدرامون ساخته شده یا نه!بله شده!حالا می‌رسیم به بخش هیجان انگیز این ماجرا که آپلود هست.در ابتدا ما باید فایل یا فایل هایی که می‌خوایم آپلود کنیم رو به NSData تبدیل کنیم. توی این آموزش من فرض رو بر این می‌گیرم که شما فایل هاژ دیتابیس کاربر رو توی یه فایل زیپ توی Document Library ذخیره کردید. برای تبدیل اون فایل به NSData از کد زیر استفاده کنیدکد آبجکتیو سی:NSData *zipData = [NSData dataWithContentsOfFile:ZipPath];کد سوئیفت:var zipData = NSData(contentsOfFile: ZipPath) as Data?حالا برای آپلود اون فایل از کد زیر استفاده می‌کنیمکد آبجکتیو سی: NSString *DropboxPath = [NSString stringWithFormat:@&quot;/Columbo/%@/%@/%@&quot;,Test,Username,ZipFileName];
  DBFILESWriteMode *mode = [[DBFILESWriteMode alloc] initWithOverwrite];
  [[[client.filesRoutes uploadData:DropboxPath
  mode:mode
  autorename:@(YES)
  clientModified:nil
  mute:@(NO)
  inputData:zipData]
  setResponseBlock:^(DBFILESFileMetadata *result, DBFILESUploadError *routeError, 
   DBRequestError *networkError) {
   if (result) {
   [self hidehud:true message:@&quot;Images Uploaded Succesfully&quot;];
   } else {
   [self hidehud:true message:@&quot;Error&quot;];
   }
   }] setProgressBlock:^(int64_t bytesUploaded, int64_t totalBytesUploaded, int64_t 
   totalBytesExpectedToUploaded) {
   NSLog(@&quot;\n%lld\n%lld\n%lld\n&quot;, bytesUploaded, totalBytesUploaded, 
   totalBytesExpectedToUploaded);
   }];کد سوئیفت:var DropboxPath = &quot;/Test/\(CompanyCode)/\(Username)/\(ZipFileName)&quot;var mode = DBFILESWriteMode()client.filesRoutes.uploadData(DropboxPath, mode: mode, autorename: true, clientModified: nil, mute: false, inputData: zipData).setResponseBlock({ result, routeError, networkError in    if result != nil {        self.hidehud(true, message: &quot;Images Uploaded Succesfully&quot;)    } else {        self.hidehud(true, message: &quot;Error&quot;)    }}).progressBlock = { bytesUploaded, totalBytesUploaded, totalBytesExpectedToUploaded in    print(String(format: &quot;\n%lld\n%lld\n%lld\n&quot;, bytesUploaded, totalBytesUploaded, totalBytesExpectedToUploaded))}در اینجا مسیری که می‌خواهیم فایل در دراپ باکس آپلود شود را به صورت String می‌نویسیم. این مسیر نیازی نیست که از قبل در دراپ باکس ساخته شده باشد. اگر وجود نداشته باشد، دراپ باکس آن را می‌سازد.بعد از این که دستور ارسال شد، ریسپانس توی responseBlock میاد که خب اگه کار رو درست انجام داده باشیم Result==True هست.همچنین شما می‌تونید روند آپلود رو توی progressBlock دریافت کنید که اون رو به صورت یک Progress Bar به کاربر نمایش بدید.به همین راحتی ما فایلمون رو توی دراپ باکس آپلود کردیم.در قسمت بعدی می‌ریم سراغ موارد یکمی پیچیده تر مثل آپلود چندین فایل به صورت همزمان، دانلود فایل روی دیوایس کاربر و گرفتن مجوز دسترسی به دراپ باکس کاربر. </description>
                <category>پوریا دلنواز</category>
                <author>پوریا دلنواز</author>
                <pubDate>Wed, 24 Oct 2018 18:10:03 +0330</pubDate>
            </item>
                    <item>
                <title>برسی مزایا و معایب تولید و توسعه اپلیکیشن با Xamarin</title>
                <link>https://virgool.io/coderlife/xamarin-vs-native-ux3mltildifi</link>
                <description>همیشه وقتی صحبت از تولید اپلیکیشن برای گوشی ها هوشمند می‌شه ذهنمون میره سمت ObjC - Swift و Java که معمول ترین روش برای تولید اپ های iOS و Android هستن. گرچه توی سال های اخیر تکنولوژی های دیگه ای برای تولید اپ معرفی شدن که هر کدوم خوبی‌ها و بدی‌های خاص خودشون‌رو دارن. این تکنولوژی ها به سرعت در حال پیشرفت هستن و هر کدوم سعی دارن که یجورایی کمبودهای تولید اپلیکیشن Native رو بپوشونن و کدنویسی برای این پلتفرما رو راحت‌تر کنن و مرز بین تولید اپلیکیشن‌های iOS و Andorid رو باریک‌تر کنن، تا جایی که بتونن محوش کنن. این تفکر ازونجایی شکل گرفت که این ایده مطرح شد:یه بار اپ بنویس و روی همه پلتفرما رانش کن! زامارین چیه؟ایده زامارین اولین بار سال ۲۰۰۱ توسط برنامه نویس های Mono بر اساس &quot;تولید نرم‌ افزار های کراس پلتفرم بر پایه DotNet&quot; مطرح شد و درنهایت در سال ۲۰۱۱ کمپانی زامارین تاسیس شد و شروع به کار کرد.مایکروسافت زامارین رو در سال ۲۰۱۶ خرید، اون رو Open Source و مجانی کرد و به صورت رسمی به Visual Studio  اضافه‌ش کرد. وقتی حرف از راه های کلیدی تولید اپ میشه، نمی‌شه زامارین رو نادیده گرفت. زامارین ابزاریه برای تولید Cross-Platform اپلیکیشن ها که به برنامه‌نویس‌ها این قابلیت رو میده که بیش از ۹۰٪ کدبیس اپلیکیشن رو به صورت یک لایه جدا بین پلت‌فرم‌های مختلف به اشتراک بذارن.حالا بهتره که بپردازیم به این که آیا زامارین روش خوبی برای تولید اپلیکیشن هست یا که نه!و برای این کار مزایا و معایب زامارین رو برسی می‌کنیم و در نهایت تصمیم نهایی رو می‌سپاریم به شما:مزایای زامارین۱. عملکرد زامارین توی اجرا و مدیریت حافظه خیلی خوب و نزدیک به Native هست.۲. زبان برنامه نویسی برای همه پلتفرمها C# هست که خب اگه بخوایم مزایای .Net رو هم در نظر نگیریم، همین یکی بودن زبان برنامه‌نویسی باعث میشه Learning curve خیلی بهتری داشته باشه. ۳. مگه میشه مزایای دات نت رو نادیده گرفت؟ دات نت فوق العاده‌س. شما وقتی از زامارین برای تولید اپلیکیشن استفاده می‌کنید، به همه کتابخونه های دات نت درسترسی دارید و میتونید ازش استفاده کنید.چیزایی مثل Lambdas, LINQ, Asynchronous programming۴. ۹۰٪ از کدبیس همه پلتفرما یکیه و نیازی نیست که برای هر پلتفرم یسری کد های پایه رو تکرار کنید و خب همه‌ی کدها روی یک لایه جدا که روی بخش Native هر پلتفرمی هست قرار میگیره و Share میشه.۵. تجربه کاربر از کار کردن با اپ زامارین، بر خلاف اپ های هایبریدی، مشابه تجربه کاربر از استفاده اپ نیتیو هست.۶. زامارین Open Source هست.۷.  نصب و راه اندازی SDK ها و IDE خیلی راحته، و روی مک و ویندوز قابل استفاده هست (برای iOS نیاز به سیمولاتور XCode هست) ۸. چیزی به نام  Xamarin Forms هم وجود داره که شما از طریقش می‌تونید واسه همه پلتفرما یه UI و یه کد بزنید که خب البته میشه همون داستان WebView و هایبریدی ها که خب ما توی این مقاله قصد نداریم وارد اون بحث شیم.۹. با زامارین میتونید واسه مک و واچ او اس هم اپ بنویسید.۱۰. درسترسی و ساپورت کامل سخت افزار و سنسور های هر پلتفرمی.معایب زامارین ۱. تاخیر توی دریافت آپدیت های SDK برای هر پلتفرمی.۲.  جامعه برنامه نویس های زامارین خیلی کوچیکتر از برنامه نویس ها نیتیو iOS و Android هست و اگه به چالشی بربخورین، کمک گرفتن برای حلش میتونه  خیلی سخت تر باشه.۳.  شما برای برنامه نویسی هر پلتفرمی نیاز به دانش اولیه برنامه نویسی برای همون پلتفرم رو دارید. چرا؟ زامارین عملا فقط SDK هر پلتفرمی رو یجورایی در قالب DotNet جا داده و خب شما صرفا نمیتونی بگی من زامارین بلدم و واسه هر پلتفرمی میتونم کد بنویسم. اگه قبلا برای پلتفرمی اپ Native تولید کرده باشید، بعد از ساختن اولین پروژه با زامارین متوجه می‌شید که این که دقیقا همونه! فقط سی شارپه! به فایل ها و کد های مثال زیر دقت کنید:پروژه Native صفر ساخته شده با XCode پروژه Xamarin صفر ساخته شده با Visual Studio ما گفتیم که زامارین فقط یک لایه Shared Code اضافه می‌کنه که شما توی همه پلتفرما می‌تونید ازش استفاده کنید. که خب اونم میتونه سرویس هایی باشه مثل کار کردن با دیتابیس لوکال یا برقراری ارتباط با بک اند سرور و کلا هر پروسسی که اپ به صورت لوکالی قراره انجام بده.پس اصلا نمیشه این ذهنیت اپ های هایبریدی رو داشته که یه بار کد میزنم و واسه هر پلتفرمی اپ تولید می‌کنم.۴.  زامارین عملکردش توی اپ هایی با پردازش گرافیکی سنگین اصلا خوب نیست و اگه می‌خواید بازی تولید کنید اصلا سمتش نرید.۵. اپلیکیشن های تولید شده با زامارین به طرز وحشتناکی پرحجم هستن و سایزشون زیاده.  یه اپ Hello World یه چیزی نزدیک به ۱۶ مگابایت می‌شه!6. اگه عادت به استفاده از کتابخونه های شخص سوم (!) و pod های مختلف دارید و یا اصلا پروژه اینو می‌طلبه، سمتش نرید چون که نمی‌تونید از کتاب خونه های Native پلتفرما استفاده کنید. گرچه خود زامارین پکیج های خاص خودشو داره ولی خب خیلی محدود تر از پکیج های Native هستن.</description>
                <category>پوریا دلنواز</category>
                <author>پوریا دلنواز</author>
                <pubDate>Wed, 29 Aug 2018 13:51:07 +0430</pubDate>
            </item>
            </channel>
</rss>