我正在尝试将练习JSON加载到表视图中,我有一个服务函数,它将来自源的数据作为JSON,以及一个视图控制器,其中包含我想要将信息加载到的表。代码中没有错误,但表加载空白行,调试部分通过打印命令显示JSON数据。我是一个初学者,所以我确定我错过了一个核心元素,但不能解决它!
api服务
package de.cowabuja.androiduriaccess;
import android.content.Intent;
import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String uriString = "content://com.android.externalstorage.documents/document/primary%3ADCIM%2FAny%2Dir%2FtheFile.txt";
Uri uri = Uri.parse(uriString);
getApplicationContext().grantUriPermission(getPackageName(), uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
}
查看控制器
...
E/AndroidRuntime: FATAL EXCEPTION: main
Process: de.cowabuja.androiduriaccess, PID: 2972
java.lang.RuntimeException: Unable to start activity ComponentInfo{de.cowabuja.androiduriaccess/de.cowabuja.androiduriaccess.MainActivity}: java.lang.SecurityException: Uid 10132 does not have permission to uri 0 @ content://com.android.externalstorage.documents/document/primary%3ADCIM%2FAny%2FDir%2FtheFile.txt
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2646)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2707)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1460)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6077)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
Caused by: java.lang.SecurityException: Uid 10132 does not have permission to uri 0 @ content://com.android.externalstorage.documents/document/primary%3ADCIM%2FAny%2FDir%2theFile.txt
at android.os.Parcel.readException(Parcel.java:1683)
at android.os.Parcel.readException(Parcel.java:1636)
at android.app.ActivityManagerProxy.grantUriPermission(ActivityManagerNative.java:4808)
at android.app.ContextImpl.grantUriPermission(ContextImpl.java:1655)
at android.content.ContextWrapper.grantUriPermission(ContextWrapper.java:712)
at de.cowabuja.androiduriaccess.MainActivity.onCreate(MainActivity.java:19)
at android.app.Activity.performCreate(Activity.java:6664)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2599)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2707)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1460)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6077)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
...
答案 0 :(得分:1)
你应该异步加载你的JSON,这意味着你应该在方法中有一个关闭,使你的alamofire调用。
class ExerciseDatabaseController: UIViewController, UITableViewDataSource, UITableViewDelegate {
//these should start with lower cases(exerciseSearchField), never uppercased
@IBOutlet weak var ExerciseSearchField: UISearchBar!
@IBOutlet weak var ExercisesTableView: UITableView!
var arrRes = [[String:AnyObject]]() // Array of dictionary
override func viewDidLoad() {
super.viewDidLoad()
//you said you would use these delegates up top when you created the class, so you have to set them
ExercisesTableView.delegate = self
ExercisesTableView.dataSource = self
fetchData()
// Do any additional setup after loading the view.
}
//this method will make the api call
//you'll notice that if you set breakpoints, it will reach the end of the method before hitting self?.arrRes = dictArray
//this is normal and how asynchronous calls work, look into tableview threading for a deeper explanation of why that is. It is super important to understand threading in iOS
//once it gets data back from the API call, it will go to the main thread and tell the tableview to reload with that data
func fetchData() {
ApiService.getExerciseData { [weak self] (dictArray) in
self?.arrRes = dictArray
print(self?.arrRes)
if self?.arrRes.count > 0 {
DispatchQueue.main.async {
self?.ExercisesTableView.reloadData()
}
}
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return arrRes.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
var dict = arrRes[indexPath.row]
cell.textLabel?.text = dict["name"] as? String
cell.detailTextLabel?.text = dict["description"] as? String
return cell
}
所以现在我们已经进行了异步调用(一般情况下,只要您通过互联网调用直观地显示信息,而这些调用尚未预先加载/保存在应用程序的某个地方)。
接下来,我们希望在tableview加载时在tableview中显示此信息。
<?php
if($_SERVER['REQUEST_METHOD']=='POST'){
//Getting values
$username = $_POST['email'];
$password = $_POST['password'];
//Creating sql query
$sql = "SELECT * FROM users WHERE email='$username' AND password='$password'";
//importing dbConnect.php script
require_once('dbConnect.php');
//executing query
$result = mysqli_query($con,$sql);
//fetching result
$check = mysqli_fetch_array($result);
//if we got some result
if(isset($check)){
//displaying success
echo "success";
}else{
//displaying failure
echo "failure";
}
mysqli_close($con);
}
你会看到我在上面使用过[弱自我]。有关异步互联网调用/使用闭包时为何需要更多解释的原因,您可以在此处阅读: http://krakendev.io/blog/weak-and-unowned-references-in-swift
有许多其他资源可供阅读iOS中弱弱和强引用/父子项目的快速谷歌搜索。此外,在iOS中研究异步/同步。这两个主题在开始时都非常重要。
答案 1 :(得分:0)
收到异步请求中的JSON数据后,重新加载tableView。所以你的
self.ExercisesTableView.reloadData()
将进入内部
Alamofire.request("https://wger.de/api/v2/exercise/?format=json").responseJSON { (responseData) -> Void in
if((responseData.result.value) != nil) {
swiftyJsonVar = JSON(responseData.result.value!)
print(swiftyJsonVar ?? nil)
}
}