Advertisement
  1. Code
  2. iOS 8

iOS 8: Membuat Widget Hari Ini

Scroll to top
Read Time: 14 min

Indonesian (Bahasa Indonesia) translation by Frida Wahyu (you can also view the original English article)

Salah satu fitur baru yang paling populer yang diperkenalkan di iOS 8 adalah kemampuan untuk membuat beberapa jenis ekstensi. Dalam tutorial ini, saya akan memandu Anda melalui proses pembuatan widget kustom untuk bagian Today di pusat notifikasi. Tetapi pertama-tama, mari kita tinjau beberapa topik tentang ekstensi dan pahami konsep-konsep penting yang benar-benar widget.

1. Apa itu Ekstensi?

Perpanjangan adalah biner tujuan khusus. Ini bukan aplikasi yang lengkap, perlu aplikasi yang berisi untuk didistribusikan. Ini bisa jadi aplikasi Anda yang sudah ada, yang dapat menyertakan satu atau beberapa ekstensi, atau yang baru dibuat. Meskipun ekstensi tidak didistribusikan secara terpisah, ia memiliki wadah sendiri.

Perpanjangan diluncurkan dan dikontrol melalui aplikasi host-nya. Mungkin Safari, misalnya, jika Anda membuat ekstensi berbagi, atau aplikasi sistem Hari Ini yang menangani pusat pemberitahuan dan widget lainnya. Setiap area sistem yang mendukung diperpanjang disebut titik ekstensi.

Untuk membuat ekstensi, Anda perlu menambahkan target ke proyek aplikasi yang berisi. Template yang disediakan oleh Xcode sudah menyertakan kerangka kerja yang sesuai untuk setiap titik ekstensi, memungkinkan aplikasi untuk berinteraksi dengan dan mengikuti kebijakan yang benar dari aplikasi host.

2. Titik Perpanjangan Hari Ini

Ekstensi yang dibuat untuk titik ekstensi hari ini, yang disebut widget, dimaksudkan untuk memberikan akses yang mudah dan cepat ke informasi. Tautan widget ke kerangka Pusat Pemberitahuan. Sangat penting bahwa Anda mendesain widget Anda dengan antarmuka pengguna yang sederhana dan terfokus, karena terlalu banyak interaksi dapat menjadi masalah. Perhatikan juga bahwa Anda tidak memiliki akses ke keyboard.

Widget diharapkan berfungsi dengan baik dan menjaga konten mereka tetap diperbarui. Kinerja adalah hal yang penting untuk dipertimbangkan. Widget Anda harus siap dengan cepat dan menggunakan sumber daya dengan bijaksana. Ini akan mencegah melambatnya seluruh pengalaman. Sistem menghentikan widget yang menggunakan terlalu banyak memori, misalnya. Widget harus sederhana dan fokus pada konten yang ditampilkan.

Itu teori yang cukup untuk saat ini. Mari mulai membuat widget khusus hari ini. Widget yang akan kami buat akan menunjukkan informasi tentang penggunaan disk, termasuk bilah kemajuan untuk memberikan referensi visual cepat bagi pengguna. Sepanjang jalan, kami juga akan mencakup konsep penting lainnya dari ekstensi iOS 8.

3. Target Setup

Langkah 1: Setup proyek

Jika Anda ingin membangun widget ini sebagai ekstensi untuk aplikasi yang sudah ada, lanjutkan dan buka proyek Xcode Anda, dan lompat ke langkah kedua. Jika Anda memulai dari awal seperti saya, maka Anda harus terlebih dahulu membuat aplikasi yang mengandung.

Buka Xcode dan di menu File pilih New> Project .... Kami akan menggunakan Objective-C sebagai bahasa pemrograman dan template Aplikasi Tampilan Tunggal untuk memulai.

Langkah 2: Tambah Target Baru

Buka menu File dan pilih New> Target .... Di kategori Ekstensi Aplikasi, pilih template Perpanjangan Hari Ini.

Anda akan melihat bahwa Proyek yang akan menjadi target ditambahkan adalah proyek yang saat ini kami kerjakan dan ekstensi akan disematkan dalam aplikasi yang berisi. Perhatikan juga bahwa ekstensi memiliki pengenal bundel yang berbeda berdasarkan pada salah satu aplikasi yang berisi, com.tutsplus.Today.Used-Space.

Klik Berikutnya, beri nama pada widget Anda, misalnya, Ruang Bekas, dan klik Selesai untuk membuat target baru. Xcode telah membuat skema baru untuk Anda dan ia akan meminta Anda untuk mengaktifkannya untuk Anda. Klik Aktifkan untuk melanjutkan.

Xcode telah membuat grup baru untuk widget bernama Space Used dan menambahkan sejumlah file ke dalamnya, subclass UIViewController dan storyboard. Itu benar, widget tidak lebih dari pengontrol tampilan dan papan cerita. Jika Anda membuka header pengontrol tampilan di editor kode, Anda akan melihat bahwa itu memang subclassing UIViewController.

Jika Anda memilih target ekstensi dari daftar target, buka tab Build Phases, dan perluas bagian Binary Link Dengan Perpustakaan, Anda akan melihat bahwa target baru terkait dengan kerangka Pusat Pemberitahuan.

4. user Interface

Kami sekarang akan membangun antarmuka pengguna dasar untuk widget kami. Menentukan ukuran widget itu penting dan ada dua cara untuk memberi tahu sistem jumlah ruang yang kita butuhkan. Salah satunya menggunakan Tata Letak Otomatis dan yang lainnya menggunakan properti preferredContentSize dari pengontrol tampilan.

Konsep tata letak adaptif juga berlaku untuk widget. Kita tidak hanya memiliki iPhone dengan berbagai lebar (dan iPad dan perangkat masa depan), tetapi juga ingat bahwa widget mungkin perlu menunjukkan kontennya dalam orientasi lanskap. Jika antarmuka pengguna dapat dijelaskan dengan kendala Tata Letak Otomatis, maka itu adalah keuntungan yang jelas bagi pengembang. Ketinggian dapat disesuaikan nanti dengan setPreferredContentSize: jika diperlukan.

Langkah 1: Menambahkan Elemen

Buka MainInterface.storyboard di editor Xcode. Anda akan melihat bahwa label yang menampilkan "Hello World" sudah ada dalam tampilan pengontrol tampilan. Pilih dan hapus dari tampilan karena kami tidak akan menggunakannya. Tambahkan label baru ke tampilan dan sejajarkan ke margin kanan seperti yang ditunjukkan di bawah ini.

Label inserted into view

Di Inspektur Atribut, setel warna teks menjadi putih, perataan teks ke kanan, dan teks label menjadi 50,0%.

Label new attributes

Pilih Ukuran untuk Fit Konten dari menu Editor Xcode untuk mengubah ukuran label dengan benar jika terlalu kecil untuk menyesuaikan isinya.

Selanjutnya, tambahkan turunan UIProgressView ke kiri label dan posisikan seperti yang ditunjukkan di bawah ini.

Progress bar inserted

Dengan tampilan progres yang dipilih, ubah atribut Progress Tint di Attributes Inspector menjadi putih dan warna Track Tint menjadi abu-abu gelap. Ini akan membuatnya lebih terlihat. Ini terlihat bagus sejauh ini. Saatnya menerapkan beberapa batasan.

Langkah 2: Menambah Batasan

Pilih label persentase dan tambahkan batas atas, bawah, dan trailing seperti yang ditunjukkan di bawah ini. Pastikan untuk tidak mencentang kotak cek Constrain to margins.

Adding constraints to label

Pilih tampilan kemajuan dan tambahkan kendala atas, memimpin, dan trailing. Gunakan kesempatan ini untuk mengubah ruang utama menjadi 3 dan jangan lupa untuk menghilangkan centang pada Constrain to margins.

Adding constraints to progress bar

Karena kami mengubah nilai kendala utama dari pandangan kemajuan, kami memiliki masalah kecil yang harus diperbaiki. Bingkai tampilan kemajuan tidak mencerminkan kendala tampilan kemajuan. Dengan tampilan kemajuan yang dipilih, klik tombol Resolve Auto Layout Issues di bagian bawah dan pilih Perbarui Bingkai dari bagian Tampilan Terpilih. Ini akan memperbarui bingkai dari pandangan kemajuan berdasarkan pada batasan yang kita atur sebelumnya.

Fixing the bar size

Langkah 3: Buat dan Jalankan

Saatnya untuk melihat widget beraksi. Dengan skema Ruang Bekas yang dipilih, pilih Jalankan dari menu Produk atau tekan Command-R. Buka pusat notifikasi dengan menggesek dari bagian atas layar ke bawah dan ketuk tombol Edit di bagian bawah pusat notifikasi. Widget Anda harus tersedia untuk ditambahkan ke bagian Hari Ini. Tambahkan ke bagian Hari ini dengan mengetuk tombol tambah di sebelah kirinya.

Seperti inilah tampilan ekstensi kita.

Itu terlihat bagus, tapi mengapa ada begitu banyak ruang di bawah tampilan dan label kemajuan? Juga, mengapa sistem operasi tidak menghargai kendala utama dari pandangan kemajuan?

Kedua masalah adalah margin standar yang ditetapkan oleh sistem operasi. Kami akan mengubahnya di langkah berikutnya. Perhatikan, bagaimanapun, bahwa margin kiri diinginkan karena menyelaraskan tampilan kemajuan dengan nama widget.

Jika Anda memutar perangkat Anda atau menjalankan aplikasi pada perangkat yang berbeda, Anda akan melihat bahwa widget menyesuaikan ukurannya dengan benar. Itu berkat Auto Layout.

Langkah 4: Memperbaiki Margin Bawah

Buka TodayViewController.m di editor Xcode. Anda akan melihat bahwa pengendali tampilan sesuai dengan protokol NCWidgetProviding. Ini berarti kita perlu mengimplementasikan metode widgetMarginInsetsForProposedMarginInsets: dan mengembalikan marjin kustom dengan mengembalikan struktur UIEdgeInsets. Perbarui implementasi metode seperti yang ditunjukkan di bawah ini.

1
- (UIEdgeInsets)widgetMarginInsetsForProposedMarginInsets:(UIEdgeInsets)margins
2
{
3
    margins.bottom = 10.0;
4
    return margins;
5
}

Jalankan aplikasi lagi untuk melihat hasilnya. Widget harus lebih kecil dengan sedikit margin di bagian bawah. Anda dapat menyesuaikan margin ini untuk mendapatkan hasil yang Anda inginkan.

Langkah 5: Menghubungkan Outlet

Sebelum melanjutkan, mari selesaikan antarmuka pengguna dengan menambahkan dua outlet. Dengan file storyboard dibuka, beralih ke asisten editor dan pastikan bahwa ini menampilkan TodayViewController.m.

Tahan Kontrol dan seret dari label ke antarmuka pengontrol tampilan untuk membuat outlet untuk label. Beri nama outlet persenLabel. Ulangi langkah ini dan buat outlet bernama barView untuk instance UIProgressView.

Connecting outletsConnecting outletsConnecting outlets

5. Menampilkan Data Nyata

Kami akan menggunakan kelas NSFileManager untuk menghitung ruang yang tersedia perangkat. Tapi bagaimana cara memperbarui widget dengan data itu?

Di sinilah metode lain dari protokol NCWidgetProviding ikut bermain. Sistem operasi memanggil metode widgetPerformUpdateWithCompletionHandler: ketika widget dimuat dan itu juga bisa disebut di latar belakang. Dalam kasus terakhir, meskipun widget tidak terlihat, sistem mungkin meluncurkannya dan meminta pembaruan untuk menyimpan snapshot. Cuplikan ini akan ditampilkan saat berikutnya widget muncul, biasanya untuk waktu yang singkat hingga widget ditampilkan.

Argumen yang dilewatkan dalam metode ini adalah penangan penyelesaian yang perlu dipanggil ketika konten atau data diperbarui. Blok tersebut mengambil parameter tipe NCUpdateResult untuk menggambarkan jika kami memiliki konten baru untuk ditampilkan. Jika tidak, sistem operasi akan tahu bahwa tidak perlu menyimpan snapshot baru.

Langkah 1: Properti

Pertama-tama kita perlu membuat beberapa properti untuk menyimpan ukuran bebas, digunakan, dan total. Kami juga akan menambahkan properti untuk menampung ruang yang digunakan pada perangkat. Ini memungkinkan kita lebih fleksibel nantinya. Tambahkan properti ini ke ekstensi kelas di TodayViewController.m.

1
@property (nonatomic, assign) unsigned long long fileSystemSize;
2
@property (nonatomic, assign) unsigned long long freeSize;
3
@property (nonatomic, assign) unsigned long long usedSize;
4
@property (nonatomic, assign) double usedRate;

Langkah 2: Menerapkan updateSizes

Selanjutnya, buat dan terapkan metode helper, updateSizes, untuk mengambil data yang diperlukan dan menghitung ruang yang digunakan perangkat.

1
- (void)updateSizes
2
{
3
    // Retrieve the attributes from NSFileManager

4
    NSDictionary *dict = [[NSFileManager defaultManager]
5
                attributesOfFileSystemForPath:NSHomeDirectory()
6
                                        error:nil];
7
8
    // Set the values

9
    self.fileSystemSize = [[dict valueForKey:NSFileSystemSize]
10
                              unsignedLongLongValue];
11
    self.freeSize       = [[dict valueForKey:NSFileSystemFreeSize]
12
                              unsignedLongLongValue];
13
    self.usedSize       = self.fileSystemSize - self.freeSize;
14
}

Langkah 3: Caching

Kita dapat memanfaatkan NSUserDefaults untuk menghemat ruang yang digunakan terhitung antara peluncuran. Siklus hidup dari sebuah widget pendek sehingga jika kita menyimpan nilai ini, kita dapat mengatur antarmuka pengguna dengan nilai awal dan kemudian menghitung nilai yang sebenarnya.

Ini juga berguna untuk menentukan apakah kita perlu memperbarui snapshot widget atau tidak. Mari kita membuat dua metode kenyamanan untuk mengakses basis data default pengguna.

1
// @implementation

2
- (double)usedRate
3
{
4
    return [[[NSUserDefaults standardUserDefaults]
5
                   valueForKey:RATE_KEY] doubleValue];
6
}
7
8
- (void)setUsedRate:(double)usedRate
9
{
10
    NSUserDefaults *defaults =
11
                       [NSUserDefaults standardUserDefaults];
12
    [defaults setValue:[NSNumber numberWithDouble:usedRate]
13
                forKey:RATE_KEY];
14
    [defaults synchronize];
15
}

Perhatikan bahwa kami menggunakan makro RATE_KEY jadi jangan lupa untuk menambahkan ini di bagian atas TodayViewController.m.

1
// Macro for NSUserDefaults key

2
#define RATE_KEY @"kUDRateUsed"

Langkah 4: Memperbarui Antarmuka Pengguna

Karena widget kami adalah pengontrol tampilan, metode viewDidLoad adalah tempat yang baik untuk memperbarui antarmuka pengguna. Kami menggunakan metode pembantu, updateInterface untuk melakukannya.

1
- (void)updateInterface
2
{
3
    double rate = self.usedRate; // retrieve the cached value

4
    self.percentLabel.text =
5
            [NSString stringWithFormat:@"%.1f%%", (rate * 100)];
6
    self.barView.progress = rate;
7
}
8
9
- (void)viewDidLoad {
10
    [super viewDidLoad];
11
    [self updateInterface];
12
}

Langkah 5: Meminjam Penangan Penyelesaian

Jumlah byte bebas cenderung berubah cukup sering. Untuk memeriksa apakah kami benar-benar perlu memperbarui widget, kami memeriksa ruang yang dihitung dan menerapkan ambang 0,01% bukan jumlah yang tepat dari byte gratis. Ubah implementasi widgetPerformUpdateWithCompletionHandler: seperti yang ditunjukkan di bawah ini.

1
- (void)widgetPerformUpdateWithCompletionHandler:(void (^)(NCUpdateResult))completionHandler
2
{
3
    
4
    [self updateSizes];
5
    
6
    double newRate = (double)self.usedSize / (double)self.fileSystemSize;
7
    
8
    if (newRate - self.usedRate < 0.0001) {
9
        completionHandler(NCUpdateResultNoData);
10
    } else {
11
        [self setUsedRate:newRate];
12
        [self updateInterface];
13
        completionHandler(NCUpdateResultNewData);
14
    }
15
}

Kami menghitung ulang ruang yang digunakan dan, jika berbeda secara signifikan dari nilai sebelumnya, simpan nilainya dan perbarui antarmuka. Kami kemudian memberi tahu sistem operasi bahwa ada sesuatu yang berubah. Jika tidak, maka tidak perlu snapshot baru. Meskipun kami tidak menggunakannya dalam contoh ini, ada juga nilai NCUpdateResultFailed untuk menunjukkan bahwa kesalahan terjadi.

Langkah 6: Buat & Jalankan

Jalankan aplikasi Anda sekali lagi. Sekarang seharusnya menampilkan nilai yang benar dari berapa banyak ruang yang digunakan oleh perangkat Anda.

6. Rekap

Mari kita tinjau siklus hidup widget baru Anda. Saat Anda membuka panel Today, sistem mungkin menampilkan snapshot sebelumnya hingga siap. Tampilan dimuat dan widget Anda akan mengambil nilai yang di-cache di NSUserDefaults dan menggunakannya untuk memperbarui antarmuka pengguna.

Selanjutnya, widgetPerformUpdateWithCompletionHandler: dipanggil dan itu akan menghitung ulang nilai yang sebenarnya. Jika nilai yang di-cache dan yang baru tidak berbeda secara signifikan, maka kita tidak melakukan apa-apa. Jika nilai baru secara substansial berbeda, kami menyimpannya dan memperbarui antarmuka pengguna yang sesuai.

Sementara di latar belakang, widget dapat diluncurkan oleh sistem operasi dan proses yang sama diulang. Jika NCUpdateResultNewData dikembalikan, snapshot baru dibuat untuk ditampilkan untuk penampilan berikutnya.

7. Menambahkan Lebih Banyak Informasi dan Animasi

Meskipun kami sudah menunjukkan ruang yang digunakan, akan menarik untuk memiliki angka yang tepat. Untuk menghindari antarmuka pengguna yang berantakan, kami akan membuat widget kami lebih interaktif. Jika pengguna mengetuk label persentase, widget akan diperluas, menunjukkan label baru dengan angka mutlak. Ini juga merupakan peluang besar untuk mempelajari cara menggunakan animasi di widget.

Langkah 1: Mengubah Antarmuka Pengguna

Buka MainInterface.storyboard dan pilih label persen. Di Inspektur Atribut, di bawah bagian Tampilan, temukan opsi Interaksi Pengguna Diaktifkan dan aktifkan.

Selanjutnya, kita perlu menghapus batasan bawah label. Jarak label ke bagian bawah tampilan akan berubah secara terprogram, yang berarti kendala akan menjadi tidak valid.

Pilih label, buka area Ukuran di Inspektur Ukuran, pilih kendala ruang bawah, dan tekan hapus. Anda juga dapat secara manual memilih panduan kendala dalam tampilan dan menghapusnya. Label sekarang hanya memiliki batasan ruang atas dan trailing seperti yang ditunjukkan di bawah ini.

Updated size attributes for percent label

Pilih pengontrol tampilan dengan mengklik yang pertama dari tiga ikon di bagian atas layar. Di area Ukuran dari Pemeriksa Ukuran, atur tinggi ke 106.

Selecting the view controller

Tambahkan label baru ke tampilan dan, seperti yang kita lakukan sebelumnya, atur warnanya ke putih di Inspektur Atribut. Selain itu, atur jumlah garis menjadi 3, tinggi menjadi 61, dan lebar 200. Ini seharusnya cukup untuk menampung tiga baris informasi. Anda juga menginginkannya sejajar dengan margin bawah dan kiri.

New label size and positioning

Langkah terakhir adalah membuka asisten editor dan membuat outlet untuk label bernama detailsLabel.

Langkah 2: Setup

Widget hanya akan diperluas untuk sesaat. Kita bisa menyimpan boolean di NSUserDefaults dan memuatnya mengingat keadaan sebelumnya, tetapi, untuk membuatnya tetap sederhana, setiap kali widget dimuat maka akan ditutup. Ketika mengetuk label persentase, informasi tambahan muncul.

Pertama-tama, tentukan dua makro di bagian atas TodayViewController.m untuk membantu dengan ukuran.

1
#define kWClosedHeight   37.0

2
#define kWExpandedHeight 106.0

Di viewDidLoad, tambahkan dua baris kode untuk mengatur tinggi awal widget dan untuk membuat label detail transparan. Kami akan memudar dalam detail label ketika label persentase disadap.

1
- (void)viewDidLoad {
2
    [super viewDidLoad];
3
    [self updateInterface];
4
    // new

5
    [self setPreferredContentSize:CGSizeMake(0.0, kWClosedHeight)];
6
    [self.detailsLabel setAlpha:0.0];
7
}

Perhatikan bahwa kami menetapkan lebar widget menjadi 0,0, karena lebar akan diatur oleh sistem operasi.

Langkah 3: Memperbarui Label Detail

Dalam label detail, kami menunjukkan nilai untuk ruang kosong, digunakan, dan total yang tersedia dengan bantuan NSByteCountFormatter. Tambahkan implementasi berikut ke pengontrol tampilan.

1
-(void)updateDetailsLabel
2
{
3
    NSByteCountFormatter *formatter =
4
                           [[NSByteCountFormatter alloc] init];
5
    [formatter setCountStyle:NSByteCountFormatterCountStyleFile];
6
7
    self.detailsLabel.text =
8
      [NSString stringWithFormat:
9
          @"Used:\t%@\nFree:\t%@\nTotal:\t%@",
10
           [formatter stringFromByteCount:self.usedSize],
11
           [formatter stringFromByteCount:self.freeSize],
12
           [formatter stringFromByteCount:self.fileSystemSize]];
13
}

Langkah 4: Menangkap Sentuhan

Untuk mendeteksi sentuhan, kami mengganti metode touchesBegan:withEvent Idenya sederhana, setiap kali sentuhan terdeteksi, widget diperluas dan label detail diperbarui. Perhatikan bahwa ukuran widget diperbarui dengan memanggil setPreferredContentSize: pada pengontrol tampilan.

1
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
2
{
3
    [self updateDetailsLabel];
4
    [self setPreferredContentSize:
5
                CGSizeMake(0.0, kWExpandedHeight)];
6
}

Langkah 5: Menambahkan Animasi

Meskipun widget berfungsi dengan baik, kami dapat meningkatkan pengalaman pengguna dengan memudarkan label detail saat widget meluas. Ini dimungkinkan jika kami menerapkan viewWillTransitionToSize: withTransitionCoordinator :. Metode ini disebut ketika ketinggian widget berubah. Karena objek koordinator transisi dilewatkan, kita dapat menyertakan animasi tambahan.

Seperti yang Anda lihat, kami mengubah nilai alfa dari label detail, tetapi Anda dapat menambahkan jenis animasi apa pun yang Anda rasa meningkatkan pengalaman pengguna.

1
-(void)viewWillTransitionToSize:(CGSize)size
2
      withTransitionCoordinator:
3
       (id<UIViewControllerTransitionCoordinator>)coordinator
4
{
5
    [coordinator animateAlongsideTransition:
6
       ^(id<UIViewControllerTransitionCoordinatorContext> context)
7
       {
8
          [self.detailsLabel setAlpha:1.0];
9
       } completion:nil];
10
}

Langkah 6: Buat & Jalankan

Kami siap menjalankan aplikasi sekali lagi. Cobalah dan ketuk label persentase untuk mengungkapkan detail baru.

Kesimpulan

Sementara semua logika ini mungkin tampak terlalu rumit untuk tugas sederhana seperti itu, Anda sekarang akan terbiasa dengan proses lengkap untuk membuat ekstensi hari ini. Ingatlah prinsip-prinsip ini saat merancang dan membangun widget Anda. Ingat untuk membuatnya tetap sederhana dan langsung, dan jangan lupakan kinerja.

Caching di sini tidak akan diperlukan sama sekali dengan operasi cepat ini, tetapi sangat penting jika Anda memiliki proses yang mahal untuk dilakukan. Gunakan pengetahuan Anda tentang pengontrol tampilan dan periksa apakah itu berfungsi untuk berbagai ukuran layar. Juga disarankan agar Anda menghindari tampilan gulir atau pengenalan sentuhan yang kompleks.

Meskipun ekstensi akan memiliki wadah terpisah, seperti yang kita lihat sebelumnya, dimungkinkan untuk mengaktifkan berbagi data antara ekstensi dan aplikasi yang mengandung. Anda juga dapat menggunakan NSExtensionContext openURLcompletionHandler: dengan skema URL khusus untuk meluncurkan aplikasi Anda dari widget. Dan jika kode adalah apa yang perlu Anda bagikan dengan ekstensi Anda, lanjutkan dan buat kerangka kerja untuk digunakan di aplikasi dan ekstensi Anda.

Saya harap pengetahuan yang disajikan di sini bermanfaat saat membangun widget hebat Anda hari ini.

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.