16 Ara 2025·6 dk okuma

SwiftUI'da doğal hissettiren form doğrulaması: odak ve hatalar

SwiftUI'da doğal hissettiren form doğrulaması: odak yönetimi, satır içi hataları doğru zamanda gösterme ve sunucu mesajlarını kullanıcıyı rahatsız etmeden net biçimde iletme.

SwiftUI'da doğal hissettiren form doğrulaması: odak ve hatalar

SwiftUI'da doğal hissettiren doğrulama nasıl görünür

Doğal hissettiren bir iOS formu sakindir. Kullanıcı yazarken onunla tartışmaz. Önemli olduğunda net geri bildirim verir ve neyin yanlış olduğunu aramanızı gerektirmez.

Ana beklenti öngörülebilirliktir. Aynı eylemler her seferinde aynı tür geri bildirime yol açmalıdır. Bir alan geçersizse, form bunu tutarlı bir yerde, tutarlı bir üslupla ve net bir sonraki adımla göstermelidir.

Çoğu formda üç tür kurala ihtiyaç duyulur:

  • Alan kuralları: Bu tek değerin geçerli olup olmadığı (boş, format, uzunluk)?
  • Alanlar arası kurallar: Değerler eşleşiyor veya birbirine bağlı mı (Parola ve Parolayı Onayla)?
  • Sunucu kuralları: Backend kabul ediyor mu (e-posta zaten kullanılmış, davet gerekiyor)?

Zamanlama, zekice sözcük seçiminden daha önemlidir. İyi doğrulama anlamlı bir anı bekler, sonra bir kez ve net konuşur. Pratik bir ritim şöyle görünür:

  • Kullanıcı yazarken sessiz kalın, özellikle format kuralları için.
  • Bir alandan çıkıldıktan sonra veya kullanıcı Gönder'e dokunduktan sonra geri bildirim gösterin.
  • Hataları düzeltilene kadar görünür tutun, sonra hemen kaldırın.

Kullanıcı hâlâ cevabı oluştururken doğrulama sessiz olmalıdır; örneğin bir e-posta veya parola yazarken. İlk karakterde hata göstermek, teknik olarak doğru olsa bile sitem gibi hissedilir.

Doğrulama, kullanıcı işinin bittiğini işaret ettiğinde görünür olmalıdır: odak başka yere gittiğinde veya gönderim denendiğinde. İşte onlar rehberlik istediği andır ve o zaman onları doğrudan hangi alanın dikkat gerektirdiğine yönlendirebilirsiniz.

Zamanlamayı doğru ayarlayın, geri kalan her şey kolaylaşır. Satır içi mesajlar kısa kalabilir, odak hareketi yardımcı hisseder ve sunucu tarafı hatalar ceza yerine normal geri bildirim gibi görünür.

Basit bir doğrulama durum modeli kurun

Doğal hissettiren bir form, temiz bir ayrımla başlar: kullanıcının yazdığı metin, uygulamanın o metne dair görüşüyle aynı şey değildir. Karıştırırsanız, ya hataları çok erken gösterirsiniz ya da UI yenilenince sunucu mesajlarını kaybedersiniz.

Basit bir yaklaşım, her alan için dört parçadan oluşan kendi durumunu vermektir: mevcut değer, kullanıcının etkileşime girip girmediği, yerel (cihaz içi) hata ve sunucu hatası (varsa). Böylece UI, her tuşa tepki vermek yerine “dokunuldu” ve “gönderildi” bazında ne gösterileceğine karar verebilir.

struct FieldState {
    var value: String = ""
    var touched: Bool = false
    var localError: String? = nil
    var serverError: String? = nil

    // One source of truth for what the UI displays
    func displayedError(submitted: Bool) -> String? {
        guard touched || submitted else { return nil }
        return localError ?? serverError
    }
}

struct FormState {
    var submitted: Bool = false
    var email = FieldState()
    var password = FieldState()
}

Birkaç küçük kural bunu öngörülebilir tutar:

  • Yerel ve sunucu hatalarını ayrı tutun. Yerel kurallar (ör. “zorunlu” veya “geçersiz e-posta”) “e-posta zaten alındı” gibi sunucu mesajının üzerine yazmamalıdır.
  • Kullanıcı o alanı tekrar düzenlediğinde serverError'ı temizleyin, böylece eski bir mesajla takılı kalmazlar.
  • touched = true yalnızca kullanıcı alanı terk ettiğinde (veya etkileşime girmeye çalıştığını kararlaştırdığınızda) ayarlayın; ilk yazılan karakterde değil.

Bununla birlikte, görünümünüz value'ya serbestçe bağlanabilir. Doğrulama localError'ı günceller, API katmanı serverError'ı ayarlar; bunlar birbirleriyle çarpışmaz.

Rehberlik eden, değil azarlayan odak yönetimi

İyi SwiftUI doğrulaması, sistem klavyenin kullanıcının görevi tamamlamasına yardımcı olması gibi hissettirmelidir; uygulamanın azarlaması gibi değil. Odak bu konuda büyük bir rol oynar.

Basit bir desen: odak durumunu tek bir gerçek kaynağı olarak @FocusState kullanarak ele alın. Alanlar için bir enum tanımlayın, her alanı ona bağlayın, sonra kullanıcı klavye düğmesine dokunduğunda ileri taşıyın.

enum Field: Hashable { case email, password, confirm }

@FocusState private var focused: Field?

TextField("Email", text: $email)
  .textContentType(.emailAddress)
  .keyboardType(.emailAddress)
  .textInputAutocapitalization(.never)
  .submitLabel(.next)
  .focused($focused, equals: .email)
  .onSubmit { focused = .password }

SecureField("Password", text: $password)
  .submitLabel(.next)
  .focused($focused, equals: .password)
  .onSubmit { focused = .confirm }

Bunu doğal hissettiren yapan şey ölçülü davranıştır. Yalnızca açık kullanıcı eylemlerinde odak değiştirin: Next, Done veya birincil düğme. Gönderim sırasında, ilk geçersiz alana odaklayın (ve gerekiyorsa kaydırın). Kullanıcı yazarken odak çalmayın, hatta değer şu an geçersiz olsa bile. Klavye etiketlerinde de tutarlılık sağlayın: ara alanlar için Next, son alan için Done.

Yaygın bir örnek Kayıt Ol’dur. Kullanıcı Create Account'a dokunur. Bir kez doğrulama yapar, hataları gösterir, sonra ilk başarısız alana (genellikle Email) odaklanır. Eğer kullanıcı Parola alanındaysa ve hâlâ yazıyor ise, onları yazma sırasında Email'e geri taşımayın. Bu küçük detay genellikle “olgun iOS formu” ile “sinir bozucu form” arasındaki farktır.

Doğru zamanda görünen satır içi hatalar

Satır içi hatalar sessiz bir ipucu gibi olmalıdır, azarlama gibi değil. “Doğal” ile “sinir bozucu” arasındaki en büyük fark mesajı ne zaman gösterdiğinizdir.

Zamanlama kuralları

Bir hata birisi yazmaya başladığı anda gösterilirse, bu kesintiye neden olur. Daha iyi bir kural: kullanıcıya alanı bitirme şansı verin.

Hatanın gösterilmesi için iyi anlar:

  • Alan odaktan çıktığında
  • Kullanıcı Gönder'e dokunduğunda
  • Yazarken kısa bir duraklamadan sonra (sadece e-posta formatı gibi bariz kontroller için)

Güvenilir bir yaklaşım: mesajı yalnızca alan dokunulduğunda veya gönderim denendiğinde gösterin. Yeni bir form sakin kalır, fakat kullanıcı etkileşime girince net rehberlik alır.

Düzen ve stil

Hata göründüğünde düzenin zıplaması iOS dışı bir his verir. Mesaj için boşluk ayırın veya görünüşünü animasyonla verin ki bir sonraki alan aniden aşağı itilmesin.

Hata metnini kısa ve spesifik tutun, mesaj başına bir düzeltme. “Parola en az 8 karakter olmalı” eyleme geçirilebilirdir. “Geçersiz giriş” ise değil.

Stil için, ince ve tutarlı olmaya çalışın. Alanın altında küçük bir font (ör. footnote), tek bir tutarlı hata rengi ve alanda nazik bir vurgulama, yoğun arka planlardan daha iyi okunur. Değer geçerli olur olmaz mesajı temizleyin.

Gerçekçi bir örnek: kayıt formunda kullanıcı name@ yazarken “E-posta geçersiz” göstermeyin. Alanı terk ettikten sonra veya kısa bir duraklamadan sonra gösterin; adres geçerli olur olmaz kaldırın.

Yerel doğrulama akışı: yazma, alanı terk etme, gönderme

Sakin bir kayıt formu oluşturun
İstemci ve sunucu doğrulaması olan bir SwiftUI kayıt akışı oluşturun.
AppMaster'ı Deneyin

İyi bir yerel akışın üç hızı vardır: yazarken nazik ipuçları, alanı terk ederken daha katı kontroller ve gönderirken tüm kurallar. Bu ritim doğrulamayı doğal hissettirir.

Kullanıcı yazarken doğrulamayı hafif ve sessiz tutun. “Bu bariz şekilde imkânsız mı?” şeklinde düşünün, “mükemmel mi?” değil. Bir e-posta alanı için sadece @ içerip boşluk içermediğini kontrol edebilirsiniz. Parola için, yazmaya başladıklarında “8+ karakter” gibi küçük bir yardımcı gösterebilirsiniz, fakat ilk tuş darbesinde kırmızı hata göstermeyin.

Kullanıcı bir alanı terk ettiğinde, daha sıkı tek alan kurallarını çalıştırın ve gerekirse satır içi hataları gösterin. Bu “Zorunlu” ve “Geçersiz format”un olduğu yerdir. Ayrıca bu, boşlukları kırpma ve girişi normalize etme (ör. e-postayı küçük harfe çevirme) zamanı olabilir, böylece kullanıcının gönderilecek şeyi görmesini sağlarsınız.

Gönderim sırasında her şeyi yeniden doğrulayın, alanlar arası kurallar da dahil. Klasik örnek Parola ve Parolayı Onayla eşleşmesi. Bu başarısız olursa, odak düzeltme gerektiren alana geçsin ve orada net bir mesaj gösterin.

Gönder düğmesini dikkatli kullanın. Kullanıcı formu doldururken düğmeyi etkin tutun. Sadece dokunmanın hiçbir şey yapmayacağı durumlarda (örneğin zaten gönderiliyor) devre dışı bırakın. Eğer geçersiz giriş nedeniyle devre dışı bırakıyorsanız, yine de neyi düzeltmeleri gerektiğini yakında gösterin.

Gönderim sırasında net bir yükleme durumu gösterin. Düğme etiketini bir ProgressView ile değiştirin, çift dokunmaları önleyin ve formu görünür tutun ki kullanıcı ne olduğunu anlasın. İstek bir saniyeden uzun sürerse, “Hesap oluşturuluyor...” gibi kısa bir etiket kaygıyı azaltır.

Kullanıcıyı sinirlendirmeyen sunucu tarafı doğrulaması

Sunucu kontrolleri nihai doğruluk kaynağıdır, yerel kontroller güçlü olsa bile. Bir parola kurallarınızı geçse de çok yaygın olduğu için reddedilebilir; bir e-posta zaten alınmış olabilir.

En büyük UX kazanımı “girdiniz kabul edilemez” ile “sunucuya ulaşılamadı”yı ayırmaktır. İstek zaman aşımına uğrarsa veya kullanıcı çevrimdışıysa, alanları geçersiz olarak işaretlemeyin. “Bağlanılamadı. Tekrar deneyin.” gibi sakin bir banner veya uyarı gösterin ve formu olduğu gibi bırakın.

Sunucu doğrulama başarısız derse, kullanıcının girdisini olduğu gibi tutun ve hatayı kesin alanlarla ilişkilendirin. Formu silmek, parolayı temizlemek veya odağı başka yere taşımak kullanıcıyı denediği için cezalandırılmış hissettirir.

Basit bir desen: yapılandırılmış bir hata yanıtını iki kovaya ayırın: alan hataları ve form düzeyi hatalar. Sonra UI durumunuzu text binding'leri değiştirmeden güncelleyin.

struct ServerValidation: Decodable {
  var fieldErrors: [String: String]
  var formError: String?
}
// Map keys like "email" or "password" to your local field IDs.

Genellikle yerel hisseden şu davranışlar beklenir:

  • Alan mesajlarını alanın hemen altında gösterin; sunucunun ifadesini açık olduğunda kullanın.
  • Odak yalnızca gönderimden sonra ilk hatalı alana götürülsün, yazma ortasında değil.
  • Sunucu birden fazla sorun döndürürse, okunabilirliği korumak için alan başına ilk mesajı gösterin.
  • Alan ayrıntılarınız varsa, “Bir şeyler ters gitti.” gibi belirsiz fallback'lere başvurmayın.

Örnek: kullanıcı kayıt formunu gönderir ve sunucu “e-posta zaten kullanılıyor” der. Yazdıkları e-posta alanın altında kalır, mesaj Email altında gösterilir ve o alana odaklanılır. Sunucuya ulaşılamadıysa, tüm alanları olduğu gibi bırakıp tek bir yeniden dene mesajı gösterin.

Sunucu mesajlarını doğru yerde gösterme

Uygulamayı ve backend'i üretin
Kullanıcıları ve kimlik bilgilerini PostgreSQL'de modelleyin, sonra uygulama ve backend'i birlikte üretin.
Projeye Başla

Sunucu hataları rastgele bir banner'da belirdiğinde “adil değil” hissi verir. Her mesajı mümkün olduğunca onu tetikleyen alana yakın gösterin. Yalnızca gerçekten tek bir girdiye bağlanamıyorsanız genel bir mesaj kullanın.

Önce sunucunun hata yükünü SwiftUI alan tanımlayıcılarınıza çevirin. Backend email, password veya profile.phone gibi anahtarlar döndürebilir; UI'nız ise Field.email ve Field.password gibi bir enum kullanıyor olabilir. Eşlemeyi yanıt alır almaz bir kere yapın, böylece görünümünüz tutarlı kalır.

Bunu modellemenin esnek bir yolu: serverFieldErrors: [Field: [String]] ve serverFormErrors: [String] tutmaktır. Her zaman birini gösteriyor olsanız bile diziler halinde saklayın. Satır içi bir hata gösterdiğinizde, en faydalı mesajı ilk olarak seçin. Örneğin, “E-posta zaten kullanılıyor” hem varsa “Geçersiz e-posta”dan daha yararlıdır.

Alan başına birden fazla hata yaygındır, ancak hepsini göstermek gürültülü olur. Çoğu durumda satır içi olarak yalnızca ilk mesajı gösterin; gerçekten ihtiyaç varsa devamı için ayrıntılar görünümü kullanın.

Bir alana bağlanamayan hatalar (oturumun süresi doldu, oran sınırı, “Daha sonra tekrar deneyin”) için bunları gönder düğmesine yakın yerleştirin ki kullanıcı eylem anında onları görsün. Ayrıca başarı olduğunda eski hataları temizlediğinizden emin olun, böylece UI “takılı” görünmez.

Son olarak, kullanıcı ilgili alanı değiştirdiğinde sunucu hatalarını temizleyin. Pratikte email için bir onChange işleyicisi serverFieldErrors[.email]'i kaldırmalıdır ki UI hemen “Tamam, düzeltiyorsun” şeklinde yansısın.

Erişilebilirlik ve üslup: yerel his veren küçük seçimler

Kod olmadan koda geçiş yapın
Gerekirse iOS, Android, web ve backend için üretime hazır kaynak kodu alın.
Kodu Üret

İyi doğrulama yalnızca mantıkla ilgili değildir. Ayrıca nasıl okunduğu, söylendiği ve Dynamic Type, VoiceOver ve farklı dillerle nasıl davrandığıyla ilgilidir.

Hataları okumayı kolaylaştırın (sadece renk ile değil)

Metnin büyük olabileceğini varsayın. Dynamic Type dostu stiller kullanın (ör. .font(.footnote) veya .font(.caption) gibi sabit boyutlar yerine) ve hata etiketlerinin satır kaydırmasına izin verin. Hata göründüğünde düzenin çok fazla zıplamasını önlemek için boşluğu tutarlı tutun.

Sadece kırmızı metne güvenmeyin. Küçük bir simge, “Hata:” öneki veya ikisi birden ekleyin. Bu renk görme sorunları olanlara yardımcı olur ve taramayı hızlandırır.

Genellikle işe yarayan hızlı kontrol listesi:

  • Dynamic Type ile ölçeklenen okunabilir bir metin stili kullanın.
  • Hata mesajlarının satır kaydırmasına izin verin ve kesme yapmaktan kaçının.
  • Renkle birlikte bir simge veya “Hata:” gibi bir etiket ekleyin.
  • Hem Açık Mod hem Karanlık Mod için kontrastı yüksek tutun.

VoiceOver'ın doğru şeyi okumasını sağlayın

Bir alan geçersiz olduğunda, VoiceOver etiket, mevcut değer ve hatayı birlikte okumalıdır. Eğer hata alanın altında ayrı bir Text ise, atlanabilir veya bağlam dışında okunabilir.

İki desen yardımcı olur:

  • Alan ve hatasını tek bir erişilebilirlik elemanında birleştirin, böylece kullanıcı alanı odakladığında hata da bildirilir.
  • Erişilebilirlik ipucu veya değeri olarak hata mesajını ekleyin (ör. “Parola, zorunlu, en az 8 karakter olmalı”).

Üslup da önemlidir. Mesajları net ve kolay yerelleştirilebilir yazın. Argo, şaka ve “Hoppala” gibi belirsiz ifadelerden kaçının. “E-posta eksik” veya “Parola bir rakam içermeli” gibi spesifik rehberlik tercih edin.

Örnek: yerel ve sunucu kuralları olan bir kayıt formu

Bir kayıt formunu hayal edin: Email, Password ve Confirm Password. Amaç, kullanıcı yazarken sessiz kalan, sonra ilerlemeye çalıştıklarında yardımcı olan bir form.

Odak sırası (Return ne yapar)

SwiftUI FocusState ile her Return tuşu doğal bir adım gibi hissettirmeli.

  • Email Return: odak Password'a geçsin.
  • Password Return: odak Confirm Password'a geçsin.
  • Confirm Password Return: klavyeyi kapatıp Gönderimi denesin.
  • Gönderim başarısız olursa: odak düzeltme gerektiren ilk alana gelsin.

Son adım önemli. Eğer e-posta geçersizse, odak sadece bir yerdeki kırmızı mesaja gitmek yerine Email alanına geri dönmelidir.

Hatalar ne zaman görünür

UI'yı sakin tutan basit bir kural: bir alan dokunulduğunda (kullanıcı onu terk ettiğinde) veya bir gönderim denendiğinde mesajları gösterin.

  • Email: alanı terk ettikten sonra veya Gönderimde “Geçerli bir e-posta girin” gösterin.
  • Password: çıkarken veya Gönderimde kuralları gösterin (ör. minimum uzunluk).
  • Confirm Password: çıkarken veya Gönderimde “Parolalar eşleşmiyor” gösterin.

Sunucu tarafı şimdi. Kullanıcı gönderir ve API şu JSON'u döndürsün:

{
  "errors": {
    "email": "That email is already in use.",
    "password": "Password is too weak. Try 10+ characters."
  }
}

Kullanıcının gördüğü: Email alanı sunucu mesajını hemen altında, Password kendi mesajını altında gösterir. Confirm Password yerel olarak başarısız olmadıkça sessiz kalır.

Sonrasında ne yaparlar: odak Email'e (ilk sunucu hatası) gelir. E-postayı değiştirir, Return ile Password'a geçer, parolayı düzeltir ve tekrar gönderir. Mesajlar satır içi ve odak niyetle hareket ettiği için form işbirlikçi, azarlayan değilmiş gibi hissettirir.

Doğrulamayı “iOS olmayan” yapan yaygın tuzaklar

Hazır olduğunda dağıt
Form hazır olduğunda üretken backend ve uygulamalarınızı buluta dağıtın.
Uygulamayı Yayınla

Bir form teknik olarak doğru olabilir ama yine de yanlış hissettirebilir. Çoğu “iOS olmayan” doğrulama sorunu zamanlamadan kaynaklanır: hatayı ne zaman gösterdiğiniz, odak nasıl hareket ediyor ve sunucuya nasıl tepki veriyorsunuz.

Yaygın hata çok erken konuşmaktır. İlk tuşdarbesinde hata gösterirseniz, insanlar yazarken azarlanıyormuş gibi hisseder. Alan dokunulduktan sonra (terk edildiğinde veya gönderim denendiğinde) beklemek genellikle bunu düzeltir.

Asenkron sunucu yanıtları da akışı bozabilir. Bir kayıt isteği döndüğünde ve ani olarak odağı başka bir alana atarsanız, bu rastgele hissedilir. Son odakta kalın ve yalnızca kullanıcı Next'a bastığında veya gönderimi işlerken odak değiştirin.

Bir diğer tuzak her düzenlemede her şeyi temizlemektir. Herhangi bir karakter değiştiğinde tüm hataları silmek gerçek problemi gizleyebilir, özellikle sunucu mesajlarıyla. Yalnızca düzenlenen alanın hatasını temizleyin, diğerlerini düzeltildikleri zamana kadar tutun.

“Sessiz başarısızlık” yapan Gönder düğmelerinden kaçının. Gönder'i açıklama olmadan sonsuza kadar devre dışı bırakmak kullanıcıları tahmin yapmaya zorlar. Devre dışı bırakıyorsanız bunu spesifik ipuçlarıyla eşleştirin veya gönderime izin verin ve sonra ilk soruna yönlendirin.

Yavaş istekler ve çift tıklamalar kolayca gözden kaçırılır. Yükleme göstermiyorsanız ve çift gönderimleri engellemiyorsanız, kullanıcı iki kez dokunur, iki yanıt alır ve kafa karıştırıcı hatalar oluşur.

Hızlı bir kontrol listesi:

  • Hataları bulanıklaşma (blur) veya gönderim için geciktirin, ilk karakter için değil.
  • Sunucu yanıtından sonra kullanıcı istemedikçe odak değiştirmeyin.
  • Hataları alan bazında temizleyin, hepsini bir anda değil.
  • Gönderimin neden bloklandığını açıklayın (ya da rehberlikle gönderime izin verin).
  • Beklerken yüklemeyi gösterin ve fazladan dokunuşları yoksayın.

Örnek: sunucu “e-posta zaten kullanılıyor” diyorsa (muhtemelen sizin AppMaster backend'inizden), mesajı Email altında tutun, Password'a dokunmayın ve kullanıcı e-postayı düzenlerken tüm formu yeniden başlatmayın.

Hızlı kontrol listesi ve sonraki adımlar

Doğal hissettiren bir doğrulama deneyimi büyük ölçüde zamanlama ve ölçülülükle ilgilidir. Katı kurallarınız olabilir ve ekran yine sakin hissedebilir.

Yayımlamadan önce bunları kontrol edin:

  • Doğru zamanda doğrulayın. Bir şeyin açıkça faydalı olmadıkça ilk tuş darbesinde hata göstermeyin.
  • Odak amaca yönelik hareket etsin. Gönderimde, ilk geçersiz alana atlayın ve neyin yanlış olduğunu belirgin yapın.
  • Kelimeleri kısa ve spesifik tutun. Kullanıcının neyi “yanlış” yaptığını değil, bir sonraki adımı söyleyin.
  • Yükleme ve yeniden denemelere saygı gösterin. Gönderilirken düğmeyi devre dışı bırakın ve istek başarısız olursa yazılan değerleri saklayın.
  • Sunucu hatalarını mümkün olduğunca alan geri bildirimi olarak ele alın. Sunucu kodlarını alana eşleyin ve gerçekten global sorunlar için üst mesaj kullanın.

Sonra gerçek bir insan gibi test edin. Küçük bir telefonu tek elinizle tutun ve başparmağınızla formu doldurmaya çalışın. Ardından VoiceOver'ı açın ve odak sırasının, hata duyurularının ve düğme etiketlerinin hâlâ mantıklı olduğundan emin olun.

Hata ayıklama ve destek için, ekran ve alan adıyla birlikte sunucu doğrulama kodlarını (ham mesajlar değil) loglamak yardımcı olur. Bir kullanıcı “kayıt olmuyor” dediğinde hangi kodun (email_taken, weak_password veya bir ağ zaman aşımı) olduğunu hızlıca söyleyebilirsiniz.

Bunu uygulama genelinde tutarlı tutmak için alan modelinizi standartlaştırın (value, touched, local error, server error), hata yerleşimini ve odak kurallarını. Her ekranı elle kodlamak istemiyorsanız ve istemci ile sunucu doğrulama kurallarını hizalı tutmak istiyorsanız, AppMaster (appmaster.io) SwiftUI uygulamaları ile beraber backend servisleri üretebilir; bu, istemci ve sunucu doğrulama kurallarını eşleştirmenizi kolaylaştırabilir.

Başlaması kolay
Harika bir şey yaratın

Ücretsiz planla AppMaster ile denemeler yapın.
Hazır olduğunuzda uygun aboneliği seçebilirsiniz.

Başlayın