Saya mencoba mengonversi potongan kode ini ke Swift. Saya berjuang untuk turun dari tanah karena beberapa kesulitan.
- (BOOL) connectedToNetwork
{
// Create zero addy
struct sockaddr_in zeroAddress;
bzero(&zeroAddress, sizeof(zeroAddress));
zeroAddress.sin_len = sizeof(zeroAddress);
zeroAddress.sin_family = AF_INET;
// Recover reachability flags
SCNetworkReachabilityRef defaultRouteReachability = SCNetworkReachabilityCreateWithAddress(NULL, (struct sockaddr *)&zeroAddress);
SCNetworkReachabilityFlags flags;
BOOL didRetrieveFlags = SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags);
CFRelease(defaultRouteReachability);
if (!didRetrieveFlags)
{
return NO;
}
BOOL isReachable = flags & kSCNetworkFlagsReachable;
BOOL needsConnection = flags & kSCNetworkFlagsConnectionRequired;
return (isReachable && !needsConnection) ? YES : NO;
}
Masalah pertama dan utama yang saya alami adalah tentang cara mendefinisikan dan bekerja dengan struct C. Pada baris pertama ( struct sockaddr_in zeroAddress;
) dari kode di atas, saya pikir mereka mendefinisikan sebuah instance yang dipanggil zeroAddress
dari struct sockaddr_in (?), Saya asumsikan. Saya mencoba menyatakan var
seperti ini.
var zeroAddress = sockaddr_in()
Tetapi saya mendapatkan kesalahan Argumen yang hilang untuk parameter 'sin_len' dalam panggilan yang dapat dimengerti karena struct itu mengambil sejumlah argumen. Jadi saya coba lagi.
var zeroAddress = sockaddr_in(sin_len: sizeof(zeroAddress), sin_family: AF_INET, sin_port: nil, sin_addr: nil, sin_zero: nil)
Seperti yang diharapkan, saya mendapatkan beberapa Variabel kesalahan lain yang digunakan dalam nilai awalnya sendiri . Saya mengerti penyebab kesalahan itu juga. Di C, mereka mendeklarasikan instance terlebih dahulu dan kemudian mengisi parameternya. Ini tidak mungkin di Swift sejauh yang saya tahu. Jadi saya benar-benar bingung pada saat ini tentang apa yang harus dilakukan.
Saya membaca dokumen resmi Apple tentang berinteraksi dengan C API di Swift tetapi tidak memiliki contoh dalam bekerja dengan struct.
Adakah yang bisa membantu saya di sini? Saya sangat menghargainya.
Terima kasih.
PEMBARUAN: Berkat Martin saya bisa melewati masalah awal. Tapi tetap saja Swift tidak membuatnya lebih mudah bagiku. Saya mendapatkan beberapa kesalahan baru.
func connectedToNetwork() -> Bool {
var zeroAddress = sockaddr_in(sin_len: 0, sin_family: 0, sin_port: 0, sin_addr: in_addr(s_addr: 0), sin_zero: (0, 0, 0, 0, 0, 0, 0, 0))
zeroAddress.sin_len = UInt8(sizeofValue(zeroAddress))
zeroAddress.sin_family = sa_family_t(AF_INET)
var defaultRouteReachability: SCNetworkReachabilityRef = SCNetworkReachabilityCreateWithAddress(UnsafePointer<Void>, UnsafePointer<zeroAddress>) // 'zeroAddress' is not a type
var flags = SCNetworkReachabilityFlags()
let didRetrieveFlags = SCNetworkReachabilityGetFlags(defaultRouteReachability, UnsafeMutablePointer<flags>) // 'flags' is not a type
defaultRouteReachability.dealloc(1) // 'SCNetworkReachabilityRef' does not have a member named 'dealloc'
if didRetrieveFlags == false {
return false
}
let isReachable: Bool = flags & kSCNetworkFlagsReachable // Cannot invoke '&' with an argument list of type '(@lvalue UInt32, Int)'
let needsConnection: Bool = flags & kSCNetworkFlagsConnectionRequired // Cannot invoke '&' with an argument list of type '(@lvalue UInt32, Int)'
return (isReachable && !needsConnection) ? true : false
}
EDIT 1: Oke saya mengubah baris ini menjadi ini,
var defaultRouteReachability: SCNetworkReachabilityRef = SCNetworkReachabilityCreateWithAddress(UnsafePointer<Void>(), &zeroAddress)
Kesalahan baru yang saya dapatkan di baris ini adalah 'UnsafePointer' tidak dapat diubah menjadi 'CFAllocator' . Bagaimana cara Anda lulus NULL
di Swift?
Juga saya mengubah baris ini dan kesalahannya hilang sekarang.
let didRetrieveFlags = SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags)
EDIT 2: Saya melewati nil
baris ini setelah melihat pertanyaan ini . Tetapi jawaban itu bertentangan dengan jawaban di sini . Dikatakan tidak ada yang setara dengan NULL
di Swift.
var defaultRouteReachability: SCNetworkReachabilityRef = SCNetworkReachabilityCreateWithAddress(nil, &zeroAddress)
Bagaimanapun saya mendapatkan kesalahan baru yang mengatakan 'sockaddr_in' tidak identik dengan 'sockaddr' di baris di atas.
Jawaban:
(Jawaban ini diperpanjang berulang kali karena perubahan dalam bahasa Swift, yang membuatnya agak membingungkan. Sekarang saya telah menulis ulang dan menghapus semua yang merujuk ke Swift 1.x. Kode lama dapat ditemukan di riwayat edit jika ada yang membutuhkan Itu.)
Beginilah cara Anda melakukannya di Swift 2.0 (Xcode 7) :
Penjelasan:
Mulai dari Swift 1.2 (Xcode 6.3), struct C yang diimpor memiliki penginisialisasi default di Swift, yang menginisialisasi semua bidang struct ke nol, sehingga struktur alamat soket dapat diinisialisasi dengan
sizeofValue()
memberikan ukuran struktur ini, ini harus diubah menjadiUInt8
untuksin_len
:AF_INET
adalahInt32
, ini harus dikonversi ke jenis yang benar untuksin_family
:withUnsafePointer(&zeroAddress) { ... }
meneruskan alamat struktur ke closure yang digunakan sebagai argumen untukSCNetworkReachabilityCreateWithAddress()
. TheUnsafePointer($0)
konversi diperlukan karena fungsi yang mengharapkan pointer kesockaddr
, tidaksockaddr_in
.Nilai yang dikembalikan dari
withUnsafePointer()
adalah nilai yang dikembalikan dariSCNetworkReachabilityCreateWithAddress()
dan yang memiliki tipeSCNetworkReachability?
, yaitu opsional. Theguard let
pernyataan (fitur baru di Swift 2.0) memberikan nilai yang terbuka kedefaultRouteReachability
variabel jika tidaknil
. Jika tidak,else
blok akan dieksekusi dan fungsinya kembali.SCNetworkReachabilityCreateWithAddress()
mengembalikan objek terkelola. Anda tidak harus merilisnya secara eksplisit.Pada Swift 2,
SCNetworkReachabilityFlags
sesuai denganOptionSetType
yang memiliki antarmuka seperti set. Anda membuat variabel bendera kosong dengandan periksa bendera dengan
Parameter kedua
SCNetworkReachabilityGetFlags
memiliki tipeUnsafeMutablePointer<SCNetworkReachabilityFlags>
, yang berarti Anda harus mengirimkan alamat variabel flags.Perhatikan juga bahwa mendaftarkan callback notifier dapat dilakukan pada Swift 2, bandingkan Bekerja dengan C API dari Swift dan Swift 2 - UnsafeMutablePointer <Void> dengan objek .
Pembaruan untuk Swift 3/4:
Pointer yang tidak aman tidak dapat dengan mudah diubah menjadi pointer dari jenis yang berbeda lagi (lihat - API UnsafeRawPointer SE-0107 ). Berikut kode yang diperbarui:
sumber
withUnsafePointer(&zeroAddress)
memanggil penutupan berikut{ ...}
dengan alamatzeroAddress
sebagai argumen. Di dalam closure,$0
singkatan dari argumen itu. - Maaf, tidak mungkin menjelaskan semua itu dalam beberapa kalimat. Lihat dokumentasi tentang penutupan di buku Swift. $ 0 adalah "nama argumen singkatan".true
jika wifi tidak terhubung dan 4G aktif tetapi pengguna telah menentukan bahwa aplikasi tidak dapat menggunakan data seluler .. Ada solusi?let cellular = flags.contains(.IsWWAN)
Anda dapat mengembalikan touple alih-alih Boolean, seperti:func connectedToNetwork() -> (connected: Bool, cellular: Bool)
Swift 3, IPv4, IPv6
Berdasarkan jawaban Martin R:
sumber
import SystemConfiguration
Ini tidak ada hubungannya dengan Swift, tetapi solusi terbaik adalah TIDAK menggunakan Reachability untuk menentukan apakah jaringan sedang online. Buat saja koneksi Anda dan tangani kesalahan jika gagal. Membuat koneksi terkadang dapat menyalakan radio offline yang tidak aktif.
Satu-satunya penggunaan Reachability yang valid adalah menggunakannya untuk memberi tahu Anda saat jaringan bertransisi dari offline ke online. Pada saat itu Anda harus mencoba kembali koneksi yang gagal.
sumber
NSURLSession
API denganNSURLSessionConfiguration.allowsCellularAccess = false
.Solusi terbaik adalah dengan menggunakan
ReachabilitySwift
kelas , tertulisSwift 2
, dan penggunaanSCNetworkReachabilityRef
.Sederhana dan mudah:
Bekerja seperti pesona.
Nikmati
sumber
SCNetworkReachability
kelas di Swift, ini adalah saran ketergantungan yang digunakan untuk memeriksa koneksi jaringan yang valid.memperbarui jawaban juanjo untuk membuat instance tunggal
Pemakaian
sumber
Ini ada di Swift 4.0
Saya menggunakan kerangka ini https://github.com/ashleymills/Reachability.swift
Dan Instal Pod ..
Di AppDelegate
Layar reachabilityViewController akan muncul jika internet tidak ada
sumber